Make math functions templates and move to misc
This commit is contained in:
parent
6e75a293a8
commit
c904014794
|
@ -25,7 +25,7 @@ set(HEADER_FILES
|
|||
io/path.h
|
||||
io/nativefilestream.h
|
||||
io/misc.h
|
||||
math/math.h
|
||||
misc/math.h
|
||||
misc/memory.h
|
||||
misc/multiarray.h
|
||||
misc/traits.h
|
||||
|
@ -52,7 +52,7 @@ set(SRC_FILES
|
|||
io/path.cpp
|
||||
io/nativefilestream.cpp
|
||||
io/misc.cpp
|
||||
math/math.cpp
|
||||
misc/math.cpp
|
||||
misc/levenshtein.cpp
|
||||
tests/testutils.cpp)
|
||||
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
#include "./math.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
/*!
|
||||
* \namespace MathUtilities
|
||||
* \brief Contains various mathematical functions.
|
||||
* \todo Move math.h and math.cpp to misc in v5.
|
||||
*/
|
||||
|
||||
namespace MathUtilities {
|
||||
|
||||
/*!
|
||||
* \brief Returns the digitsum of the given \a number using the specified \a base.
|
||||
* \todo Make constexpr/template in v5.
|
||||
*/
|
||||
int digitsum(int number, int base)
|
||||
{
|
||||
int res = 0;
|
||||
while (number > 0) {
|
||||
res += number % base;
|
||||
number /= base;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the factorial of the given \a number.
|
||||
* \todo Make constexpr/template in v5.
|
||||
*/
|
||||
int factorial(int number)
|
||||
{
|
||||
int res = 1;
|
||||
for (int i = 1; i <= number; ++i) {
|
||||
res *= i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes \a base power \a exponent modulo \a module.
|
||||
* \todo Make constexpr/template in v5.
|
||||
*/
|
||||
std::uint64_t powerModulo(const std::uint64_t base, const std::uint64_t exponent, const std::uint64_t module)
|
||||
{
|
||||
std::uint64_t res = 1;
|
||||
for (std::uint64_t mask = 0x8000000000000000; mask; mask >>= 1) {
|
||||
if (mask & exponent) {
|
||||
res *= base;
|
||||
}
|
||||
if (mask != 1) {
|
||||
res *= res;
|
||||
}
|
||||
res %= module;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the inverse of \a number modulo \a module.
|
||||
* \todo Make constexpr/template in v5.
|
||||
*/
|
||||
std::int64_t inverseModulo(std::int64_t number, std::int64_t module)
|
||||
{
|
||||
std::int64_t y1 = 0, y2 = 1, tmp;
|
||||
while (number != 1) {
|
||||
tmp = y1 - (module / number) * y2;
|
||||
y1 = y2;
|
||||
y2 = tmp;
|
||||
tmp = module % number;
|
||||
module = number;
|
||||
number = tmp;
|
||||
}
|
||||
return y2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the order of \a number modulo \a module.
|
||||
* \todo Make constexpr/template in v5.
|
||||
*/
|
||||
std::uint64_t orderModulo(const std::uint64_t number, const std::uint64_t module)
|
||||
{
|
||||
std::uint64_t order = 1;
|
||||
for (; powerModulo(number, order, module) != 1 && order != module; ++order)
|
||||
;
|
||||
return order != module ? order : 0;
|
||||
}
|
||||
} // namespace MathUtilities
|
42
math/math.h
42
math/math.h
|
@ -1,42 +0,0 @@
|
|||
#ifndef MATHUTILITIES_H
|
||||
#define MATHUTILITIES_H
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace MathUtilities {
|
||||
|
||||
CPP_UTILITIES_EXPORT int digitsum(int number, int base = 10);
|
||||
CPP_UTILITIES_EXPORT int factorial(int number);
|
||||
CPP_UTILITIES_EXPORT std::uint64_t powerModulo(std::uint64_t base, std::uint64_t expontent, std::uint64_t module);
|
||||
CPP_UTILITIES_EXPORT std::int64_t inverseModulo(std::int64_t number, std::int64_t module);
|
||||
CPP_UTILITIES_EXPORT std::uint64_t orderModulo(std::uint64_t number, std::uint64_t module);
|
||||
|
||||
/// \brief Returns the smallest of the given items.
|
||||
template <typename T> constexpr T min(T first, T second)
|
||||
{
|
||||
return first < second ? first : second;
|
||||
}
|
||||
|
||||
/// \brief Returns the smallest of the given items.
|
||||
template <typename T1, typename... T2> constexpr T1 min(T1 first, T1 second, T2... remaining)
|
||||
{
|
||||
return first < second ? min(first, remaining...) : min(second, remaining...);
|
||||
}
|
||||
|
||||
/// \brief Returns the greatest of the given items.
|
||||
template <typename T> constexpr T max(T first, T second)
|
||||
{
|
||||
return first > second ? first : second;
|
||||
}
|
||||
|
||||
/// \brief Returns the greatest of the given items.
|
||||
template <typename T1, typename... T2> constexpr T1 max(T1 first, T1 second, T2... remaining)
|
||||
{
|
||||
return first > second ? max(first, remaining...) : max(second, remaining...);
|
||||
}
|
||||
|
||||
} // namespace MathUtilities
|
||||
|
||||
#endif // MATHUTILITIES_H
|
|
@ -1,7 +1,7 @@
|
|||
#include "./levenshtein.h"
|
||||
#include "./multiarray.h"
|
||||
|
||||
#include "../math/math.h"
|
||||
#include "./math.h"
|
||||
#include "./multiarray.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include "./math.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
/*!
|
||||
* \namespace MathUtilities
|
||||
* \brief Contains various mathematical functions.
|
||||
*/
|
||||
|
||||
namespace MathUtilities {
|
||||
|
||||
} // namespace MathUtilities
|
|
@ -0,0 +1,113 @@
|
|||
#ifndef MATHUTILITIES_H
|
||||
#define MATHUTILITIES_H
|
||||
|
||||
#include "../global.h"
|
||||
#include "./traits.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace MathUtilities {
|
||||
|
||||
/*!
|
||||
* \brief Returns the digitsum of the given \a number using the specified \a base.
|
||||
*/
|
||||
template <typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>> * = nullptr>
|
||||
constexpr IntegralType digitsum(IntegralType number, IntegralType base = 10)
|
||||
{
|
||||
IntegralType res = 0;
|
||||
while (number > 0) {
|
||||
res += number % base;
|
||||
number /= base;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the factorial of the given \a number.
|
||||
*/
|
||||
template <typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>> * = nullptr> constexpr IntegralType factorial(IntegralType number)
|
||||
{
|
||||
IntegralType res = 1;
|
||||
for (IntegralType i = 1; i <= number; ++i) {
|
||||
res *= i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes \a base power \a exponent modulo \a module.
|
||||
*/
|
||||
template <typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
|
||||
constexpr IntegralType powerModulo(const IntegralType base, const IntegralType exponent, const IntegralType module)
|
||||
{
|
||||
IntegralType res = 1;
|
||||
for (IntegralType mask = static_cast<IntegralType>(1) << static_cast<IntegralType>(sizeof(IntegralType) * 8 - 1); mask; mask >>= 1) {
|
||||
if (mask & exponent) {
|
||||
res *= base;
|
||||
}
|
||||
if (mask != 1) {
|
||||
res *= res;
|
||||
}
|
||||
res %= module;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the inverse of \a number modulo \a module.
|
||||
*/
|
||||
template <typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
|
||||
constexpr IntegralType inverseModulo(IntegralType number, IntegralType module)
|
||||
{
|
||||
IntegralType y1 = 0, y2 = 1, tmp;
|
||||
while (number != 1) {
|
||||
tmp = y1 - (module / number) * y2;
|
||||
y1 = y2;
|
||||
y2 = tmp;
|
||||
tmp = module % number;
|
||||
module = number;
|
||||
number = tmp;
|
||||
}
|
||||
return y2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the order of \a number modulo \a module.
|
||||
*/
|
||||
template <typename IntegralType, Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
|
||||
constexpr IntegralType orderModulo(const IntegralType number, const IntegralType module)
|
||||
{
|
||||
IntegralType order = 1;
|
||||
for (; powerModulo(number, order, module) != 1 && order != module; ++order)
|
||||
;
|
||||
return order != module ? order : 0;
|
||||
}
|
||||
|
||||
/// \brief Returns the smallest of the given items.
|
||||
template <typename T> constexpr T min(T first, T second)
|
||||
{
|
||||
return first < second ? first : second;
|
||||
}
|
||||
|
||||
/// \brief Returns the smallest of the given items.
|
||||
template <typename T1, typename... T2> constexpr T1 min(T1 first, T1 second, T2... remaining)
|
||||
{
|
||||
return first < second ? min(first, remaining...) : min(second, remaining...);
|
||||
}
|
||||
|
||||
/// \brief Returns the greatest of the given items.
|
||||
template <typename T> constexpr T max(T first, T second)
|
||||
{
|
||||
return first > second ? first : second;
|
||||
}
|
||||
|
||||
/// \brief Returns the greatest of the given items.
|
||||
template <typename T1, typename... T2> constexpr T1 max(T1 first, T1 second, T2... remaining)
|
||||
{
|
||||
return first > second ? max(first, remaining...) : max(second, remaining...);
|
||||
}
|
||||
|
||||
} // namespace MathUtilities
|
||||
|
||||
#endif // MATHUTILITIES_H
|
|
@ -1,4 +1,4 @@
|
|||
#include "../math/math.h"
|
||||
#include "../misc/math.h"
|
||||
#include "../tests/testutils.h"
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
@ -66,19 +66,19 @@ void MathTests::testFactorial()
|
|||
|
||||
void MathTests::testPowerModulo()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(25_uint64, powerModulo(5, 2, 30));
|
||||
CPPUNIT_ASSERT_EQUAL(5_uint64, powerModulo(5, 2, 20));
|
||||
CPPUNIT_ASSERT_EQUAL(25u, powerModulo(5u, 2u, 30u));
|
||||
CPPUNIT_ASSERT_EQUAL(5u, powerModulo(5u, 2u, 20u));
|
||||
}
|
||||
|
||||
void MathTests::testInverseModulo()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(-12_int64, inverseModulo(2, 25));
|
||||
CPPUNIT_ASSERT_EQUAL(-8_int64, inverseModulo(3, 25));
|
||||
CPPUNIT_ASSERT_EQUAL(-12u, inverseModulo(2u, 25u));
|
||||
CPPUNIT_ASSERT_EQUAL(-8u, inverseModulo(3u, 25u));
|
||||
}
|
||||
|
||||
void MathTests::testOrderModulo()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(20_uint64, orderModulo(2, 25));
|
||||
CPPUNIT_ASSERT_EQUAL(5_uint64, orderModulo(6, 25));
|
||||
CPPUNIT_ASSERT_EQUAL(0_uint64, orderModulo(5, 25));
|
||||
CPPUNIT_ASSERT_EQUAL(20u, orderModulo(2u, 25u));
|
||||
CPPUNIT_ASSERT_EQUAL(5u, orderModulo(6u, 25u));
|
||||
CPPUNIT_ASSERT_EQUAL(0u, orderModulo(5u, 25u));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue