diff --git a/src/blackmisc/math/mathutils.cpp b/src/blackmisc/math/mathutils.cpp index 8fe8e957b..70ab33e3f 100644 --- a/src/blackmisc/math/mathutils.cpp +++ b/src/blackmisc/math/mathutils.cpp @@ -93,5 +93,21 @@ namespace BlackMisc return r % ((high + 1) - low) + low; } + int CMathUtils::roundToMultipleOf(int value, int divisor) + { + Q_ASSERT(divisor != 0); + Q_ASSERT(divisor >= - std::numeric_limits::max()); + divisor = std::abs(divisor); + Q_ASSERT(std::abs(value) < std::numeric_limits::max() - divisor / 2); + + int multiplier = value / divisor; + int remainder = std::abs(value % divisor); + int shortfall = divisor - remainder; + + if (shortfall < remainder) { multiplier += value < 0 ? -1 : 1; } + + return multiplier * divisor; + } + } // namespace } // namespace diff --git a/src/blackmisc/math/mathutils.h b/src/blackmisc/math/mathutils.h index 291af43bd..edc7deefb 100644 --- a/src/blackmisc/math/mathutils.h +++ b/src/blackmisc/math/mathutils.h @@ -101,6 +101,9 @@ namespace BlackMisc //! Random number between low and high static int randomInteger(int low, int high); + + //! Round numToRound to the nearest multiple of multiple + static int roundToMultipleOf(int value, int divisor); }; } // namespace diff --git a/tests/blackmisc/testblackmiscmain.cpp b/tests/blackmisc/testblackmiscmain.cpp index 3490a0426..706fb8922 100644 --- a/tests/blackmisc/testblackmiscmain.cpp +++ b/tests/blackmisc/testblackmiscmain.cpp @@ -17,6 +17,7 @@ #include "testvaluecache.h" #include "testblackmiscmain.h" #include "testweather.h" +#include "testmath.h" namespace BlackMiscTest { @@ -36,6 +37,7 @@ namespace BlackMiscTest CTestIdentifier identifierTests; CTestValueCache valueCacheTests; CTestWeather weatherTests; + CTestMath mathTests; status |= QTest::qExec(&pqBaseTests, argc, argv); status |= QTest::qExec(&avBaseTests, argc, argv); status |= QTest::qExec(&geoTests, argc, argv); @@ -45,6 +47,7 @@ namespace BlackMiscTest status |= QTest::qExec(&inputTests, argc, argv); status |= QTest::qExec(&valueCacheTests, argc, argv); status |= QTest::qExec(&weatherTests, argc, argv); + status |= QTest::qExec(&mathTests, argc, argv); } return status; } diff --git a/tests/blackmisc/testmath.cpp b/tests/blackmisc/testmath.cpp new file mode 100644 index 000000000..f1bc84fad --- /dev/null +++ b/tests/blackmisc/testmath.cpp @@ -0,0 +1,38 @@ +/* Copyright (C) 2016 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "testmath.h" +#include "blackmisc/math/mathutils.h" + +using namespace BlackMisc::Math; + +namespace BlackMiscTest +{ + void CTestMath::testRoundToMultipleOf() + { + QVERIFY2(CMathUtils::roundToMultipleOf(0, 3) == 0, "Nearest multiple of 3 from 0 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(1, 3) == 0, "Nearest multiple of 3 from 1 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(2, 3) == 3, "Nearest multiple of 3 from 2 should be 3"); + QVERIFY2(CMathUtils::roundToMultipleOf(3, 3) == 3, "Nearest multiple of 3 from 3 should be 3"); + + QVERIFY2(CMathUtils::roundToMultipleOf(0, -3) == 0, "Nearest multiple of -3 from 0 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(1, -3) == 0, "Nearest multiple of -3 from 1 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(2, -3) == 3, "Nearest multiple of -3 from 2 should be 3"); + QVERIFY2(CMathUtils::roundToMultipleOf(3, -3) == 3, "Nearest multiple of -3 from 3 should be 3"); + + QVERIFY2(CMathUtils::roundToMultipleOf(-1, 3) == 0, "Nearest multiple of 3 from -1 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(-2, 3) == -3, "Nearest multiple of 3 from -2 should be -3"); + QVERIFY2(CMathUtils::roundToMultipleOf(-3, 3) == -3, "Nearest multiple of 3 from -3 should be -3"); + + QVERIFY2(CMathUtils::roundToMultipleOf(-1, -3) == 0, "Nearest multiple of -3 from -1 should be 0"); + QVERIFY2(CMathUtils::roundToMultipleOf(-2, -3) == -3, "Nearest multiple of -3 from -2 should be -3"); + QVERIFY2(CMathUtils::roundToMultipleOf(-3, -3) == -3, "Nearest multiple of -3 from -3 should be -3"); + } + +} // namespace diff --git a/tests/blackmisc/testmath.h b/tests/blackmisc/testmath.h new file mode 100644 index 000000000..38526d47c --- /dev/null +++ b/tests/blackmisc/testmath.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2016 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISCTEST_TESTMATH_H +#define BLACKMISCTEST_TESTMATH_H + +#include + +namespace BlackMiscTest +{ + + //! Math classes tests + class CTestMath : public QObject + { + Q_OBJECT + + public: + //! Standard test case constructor + explicit CTestMath(QObject *parent = nullptr) : QObject(parent) {} + + private slots: + //! Unit test for round to multiple of + void testRoundToMultipleOf(); + }; + +} // namespace + +#endif // guard