File indexing completed on 2024-04-28 15:11:56

0001 /*
0002     SPDX-FileCopyrightText: 2016 Akarsh Simha <akarsh.simha@kdemail.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "testcachingdms.h"
0008 
0009 #include "auxiliary/cachingdms.h"
0010 
0011 #include <QTest>
0012 
0013 #include <ctime>
0014 #include <cstdlib>
0015 #include <cstdint>
0016 
0017 TestCachingDms::TestCachingDms() : QObject()
0018 {
0019 }
0020 
0021 void TestCachingDms::defaultCtor()
0022 {
0023     /*
0024      * Test 1: Check Default Constructor
0025     */
0026 
0027     // Check default empty constructor
0028     CachingDms d;
0029     QVERIFY(std::isnan(d.Degrees()));
0030     QVERIFY(std::isnan(d.sin()));
0031     QVERIFY(std::isnan(d.cos()));
0032 }
0033 
0034 void TestCachingDms::explicitSexigesimalCtor()
0035 {
0036     /*
0037      * Test 2: Checks Sexigesimal Ctor
0038     */
0039 
0040     // DD:MM:SS
0041     // 14:55:20
0042 
0043     CachingDms d(14, 55, 20);
0044 
0045     QVERIFY(d.degree() == 14);
0046     QVERIFY(d.arcmin() == 55);
0047     QVERIFY(d.arcsec() == 20);
0048     QVERIFY(qFuzzyCompare(d.Degrees(), (14.0 + 55.0 / 60.0 + 20.0 / 3600.0)));
0049     QVERIFY(fabs(d.sin() - .25750758368074941632) < 1e-9);
0050     QVERIFY(fabs(d.cos() - .96627627744186177805) < 1e-9);
0051 }
0052 
0053 void TestCachingDms::angleCtor()
0054 {
0055     /*
0056      * Test 3: Checks Angle Ctor
0057     */
0058 
0059     // Angle = -112.56 Degrees ---> HMS (16:29:45)
0060 
0061     double angle = -112.56;
0062 
0063     CachingDms d(angle);
0064 
0065     QVERIFY(d.degree() == (int)angle);
0066 
0067     QVERIFY(qFuzzyCompare(d.Hours(), (angle + 360) / 15.0));
0068     QVERIFY(d.hour() == 16);
0069     QVERIFY(d.minute() == 29);
0070     QVERIFY(d.second() == 45);
0071     QVERIFY(fabs(d.sin() + 0.92347828085768229015) < 1e-9);
0072     QVERIFY(fabs(d.cos() + 0.38365070674265630377) < 1e-9);
0073 }
0074 
0075 void TestCachingDms::stringCtor()
0076 {
0077     QString hms("14:55:20");
0078 
0079     // From Degree
0080     CachingDms d(hms);
0081 
0082     QVERIFY(d.degree() == 14);
0083     QVERIFY(d.arcmin() == 55);
0084     QVERIFY(d.arcsec() == 20);
0085     QVERIFY(qFuzzyCompare(d.Degrees(), (14.0 + 55.0 / 60.0 + 20.0 / 3600.0)));
0086     QVERIFY(fabs(d.sin() - .25750758368074941632) < 1e-9);
0087     QVERIFY(fabs(d.cos() - .96627627744186177805) < 1e-9);
0088 
0089     // From Hours
0090     CachingDms h(hms, false);
0091     QVERIFY(qFuzzyCompare(h.Degrees(), d.Degrees() * 15.0));
0092     QVERIFY(qFuzzyCompare(h.Hours(), d.Degrees()));
0093 }
0094 
0095 void TestCachingDms::setUsing_asin()
0096 {
0097     // Test case in first quadrant: 56.3 degrees
0098     CachingDms d;
0099     d.setUsing_asin(.83195412213048254606);
0100     QVERIFY(fabs(d.Degrees() - 56.3) < 1e-7);
0101     QVERIFY(fabs(d.cos() - .55484442744799927555) < 1e-9);
0102 
0103     // Test case in fourth quadrant: -56.3 degrees
0104     d.setUsing_asin(-.83195412213048254606);
0105     QVERIFY(fabs(d.Degrees() + 56.3) < 1e-7);
0106     QVERIFY(fabs(d.cos() - .55484442744799927555) < 1e-9);
0107 }
0108 
0109 void TestCachingDms::setUsing_acos()
0110 {
0111     CachingDms d;
0112 
0113     // Test case in first quadrant: 56.3 degrees
0114     d.setUsing_acos(.55484442744799927555);
0115     QVERIFY(fabs(d.Degrees() - 56.3) < 1e-7);
0116     QVERIFY(fabs(d.sin() - .83195412213048254606) < 1e-9);
0117 
0118     // Test case in second quadrant: 123.7 degrees
0119     d.setUsing_acos(-0.55484442744799927555);
0120     QVERIFY(fabs(d.Degrees() - 123.7) < 1e-7);
0121     QVERIFY(fabs(d.sin() - .83195412213048254606) < 1e-9);
0122 }
0123 
0124 void TestCachingDms::setUsing_atan2()
0125 {
0126     // Test case in first quadrant: 56.3 degrees
0127     CachingDms d;
0128     d.setUsing_atan2(2.73701935509448143467, 1.82536500102022632674);
0129     QVERIFY(fabs(d.Degrees() - 56.3) < 1e-7);
0130     QVERIFY(fabs(d.sin() - .83195412213048254606) < 1e-9);
0131     QVERIFY(fabs(d.cos() - .55484442744799927555) < 1e-9);
0132 
0133     // Test case in third quadrant: -123.7 degrees
0134     d.setUsing_atan2(-2.73701935509448143467, -1.82536500102022632674);
0135     QVERIFY(fabs(d.Degrees() + 123.7) < 1e-7);
0136     QVERIFY(fabs(d.sin() + .83195412213048254606) < 1e-9);
0137     QVERIFY(fabs(d.cos() + .55484442744799927555) < 1e-9);
0138 
0139     // Test case in second quadrant: 123.7 degrees
0140     d.setUsing_atan2(2.73701935509448143467, -1.82536500102022632674);
0141     QVERIFY(fabs(d.Degrees() - 123.7) < 1e-7);
0142     QVERIFY(fabs(d.sin() - .83195412213048254606) < 1e-9);
0143     QVERIFY(fabs(d.cos() + .55484442744799927555) < 1e-9);
0144 
0145     // Test case in fourth quadrant: -56.3 degrees
0146     d.setUsing_atan2(-2.73701935509448143467, +1.82536500102022632674);
0147     QVERIFY(fabs(d.Degrees() + 56.3) < 1e-7);
0148     QVERIFY(fabs(d.sin() + .83195412213048254606) < 1e-9);
0149     QVERIFY(fabs(d.cos() - .55484442744799927555) < 1e-9);
0150 
0151     // Edge case test: angle = 0
0152     d.setUsing_atan2(0., 1.33);
0153     QVERIFY(fabs(d.Degrees() - 0.) < 1e-7);
0154     QVERIFY(fabs(d.sin() - 0.) < 1e-9);
0155     QVERIFY(fabs(d.cos() - 1.) < 1e-9);
0156 
0157     // Edge case test: angle = 90 degrees
0158     d.setUsing_atan2(10.12, 0.);
0159     QVERIFY(fabs(d.Degrees() - 90.) < 1e-7);
0160     QVERIFY(fabs(d.sin() - 1.) < 1e-9);
0161     QVERIFY(fabs(d.cos() - 0.) < 1e-9);
0162 
0163     // Edge case test: angle = -90 degrees
0164     d.setUsing_atan2(-3.1415, 0.);
0165     QVERIFY(fabs(d.Degrees() + 90.) < 1e-7);
0166     QVERIFY(fabs(d.sin() + 1.) < 1e-9);
0167     QVERIFY(fabs(d.cos() - 0.) < 1e-9);
0168 
0169     // Edge case test: angle = 180 degrees
0170     d.setUsing_atan2(0., -724.);
0171     QVERIFY(fabs(d.Degrees() - 180.) < 1e-7);
0172     QVERIFY(fabs(d.sin() - 0.) < 1e-9);
0173     QVERIFY(fabs(d.cos() + 1.) < 1e-9);
0174 }
0175 
0176 void TestCachingDms::unaryMinusOperator()
0177 {
0178     CachingDms d(56.3);
0179     qDebug() << (-d).Degrees();
0180     QVERIFY(qFuzzyCompare((-d).Degrees(), -56.3));
0181     QVERIFY(qFuzzyCompare((-d).cos(), d.cos()));
0182     QVERIFY(qFuzzyCompare((-d).sin(), -d.sin()));
0183 }
0184 
0185 void TestCachingDms::additionOperator()
0186 {
0187     const double a = 123.7;
0188     const double b = 89.5;
0189     CachingDms d1(a);
0190     CachingDms d2(b);
0191     CachingDms ds       = d1 + d2;
0192     const double sinapb = std::sin((a + b) * dms::DegToRad);
0193     const double cosapb = std::cos((a + b) * dms::DegToRad);
0194     QVERIFY(fabs(ds.sin() - sinapb) < 1e-9);
0195     QVERIFY(fabs(ds.cos() - cosapb) < 1e-9);
0196 
0197     const double c = -34.7;
0198     const double d = 233.6;
0199     CachingDms d3(c);
0200     CachingDms d4(d);
0201     CachingDms ds2      = d3 + d4;
0202     const double sincpd = std::sin((c + d) * dms::DegToRad);
0203     const double coscpd = std::cos((c + d) * dms::DegToRad);
0204     QVERIFY(fabs(ds2.sin() - sincpd) < 1e-9);
0205     QVERIFY(fabs(ds2.cos() - coscpd) < 1e-9);
0206 }
0207 
0208 void TestCachingDms::subtractionOperator()
0209 {
0210     const double a = 123.7;
0211     const double b = 89.5;
0212     CachingDms d1(a);
0213     CachingDms d2(b);
0214     CachingDms ds       = d1 - d2;
0215     const double sinamb = std::sin((a - b) * dms::DegToRad);
0216     const double cosamb = std::cos((a - b) * dms::DegToRad);
0217     QVERIFY(fabs(ds.sin() - sinamb) < 1e-9);
0218     QVERIFY(fabs(ds.cos() - cosamb) < 1e-9);
0219 
0220     const double c = -34.7;
0221     const double d = 233.6;
0222     CachingDms d3(c);
0223     CachingDms d4(d);
0224     CachingDms ds2      = d3 - d4;
0225     const double sincmd = std::sin((c - d) * dms::DegToRad);
0226     const double coscmd = std::cos((c - d) * dms::DegToRad);
0227     QVERIFY(fabs(ds2.sin() - sincmd) < 1e-9);
0228     QVERIFY(fabs(ds2.cos() - coscmd) < 1e-9);
0229 }
0230 
0231 void TestCachingDms::testFailsafeUseOfBaseClassPtr()
0232 {
0233     typedef union angle {
0234         double x;
0235         int64_t y;
0236     } angle;
0237     const int testCases = 5000;
0238     std::srand(std::time(nullptr));
0239     for (int k = 0; k < testCases; ++k)
0240     {
0241         angle a { 0 };
0242         CachingDms _a;
0243         dms __a;
0244         a.y = std::rand();
0245         _a.setD(a.x);
0246         __a.setD(a.x);
0247         dms *d;
0248         if (std::rand() % 10 > 5)
0249             d = &_a;
0250         else
0251             d = &__a;
0252         angle b;
0253         b.y = std::rand();
0254         switch (std::rand() % 7)
0255         {
0256             case 0:
0257                 d->setD(b.x);
0258                 break;
0259             case 1:
0260                 d->setH(b.x / 15.);
0261                 break;
0262             case 2:
0263             {
0264                 dms x(b.x);
0265                 d->setD(x.degree(), x.arcmin(), x.arcsec(), x.marcsec());
0266                 break;
0267             }
0268             case 3:
0269             {
0270                 dms x(b.x);
0271                 d->setFromString(x.toDMSString());
0272                 break;
0273             }
0274             case 4:
0275             {
0276                 dms x(b.x);
0277                 d->setFromString(x.toHMSString(), false);
0278                 break;
0279             }
0280             case 5:
0281             {
0282                 dms x(b.x);
0283                 dms y(0.0);
0284                 *d = x + y;
0285                 break;
0286             }
0287             case 6:
0288             default:
0289                 d->setRadians(b.x * dms::DegToRad);
0290                 break;
0291         }
0292         QVERIFY(fabs(d->sin() - sin(b.x * dms::DegToRad)) < 1e-12);
0293         QVERIFY(fabs(d->cos() - cos(b.x * dms::DegToRad)) < 1e-12);
0294     }
0295 }
0296 
0297 QTEST_GUILESS_MAIN(TestCachingDms)