2015-09-06 20:19:09 +02:00
|
|
|
#include "./math.h"
|
2015-04-22 18:36:40 +02:00
|
|
|
|
|
|
|
#include <cassert>
|
2017-05-01 03:13:11 +02:00
|
|
|
#include <cstdlib>
|
2015-04-22 18:36:40 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \namespace MathUtilities
|
|
|
|
* \brief Contains various mathematical functions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
2016-01-27 00:15:01 +01:00
|
|
|
* \brief Returns a pseudo random number between \a lowerbounds and \a upperbounds.
|
|
|
|
* \remarks Might be removed since std::uniform_int_distribution does the same.
|
2015-04-22 18:36:40 +02:00
|
|
|
*/
|
|
|
|
int MathUtilities::random(int lowerbounds, int upperbounds)
|
|
|
|
{
|
|
|
|
assert(upperbounds - lowerbounds < RAND_MAX);
|
|
|
|
return lowerbounds + std::rand() % (upperbounds - lowerbounds + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2016-01-27 00:15:01 +01:00
|
|
|
* \brief Returns the digitsum of the given \a number using the specified \a base.
|
2015-04-22 18:36:40 +02:00
|
|
|
*/
|
|
|
|
int MathUtilities::digitsum(int number, int base)
|
|
|
|
{
|
|
|
|
int res = 0;
|
2017-05-01 03:13:11 +02:00
|
|
|
while (number > 0) {
|
2015-04-22 18:36:40 +02:00
|
|
|
res += number % base;
|
|
|
|
number /= base;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2016-01-27 00:15:01 +01:00
|
|
|
* \brief Returns the factorial of the given \a number.
|
2015-04-22 18:36:40 +02:00
|
|
|
*/
|
|
|
|
int MathUtilities::factorial(int number)
|
|
|
|
{
|
|
|
|
int res = 1;
|
2017-05-01 03:13:11 +02:00
|
|
|
for (int i = 1; i <= number; ++i) {
|
2015-04-22 18:36:40 +02:00
|
|
|
res *= i;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2016-01-27 00:15:01 +01:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Computes \a base power \a exponent modulo \a module.
|
|
|
|
*/
|
|
|
|
uint64 powerModulo(const uint64 base, const uint64 exponent, const uint64 module)
|
|
|
|
{
|
|
|
|
uint64 res = 1;
|
2017-05-01 03:13:11 +02:00
|
|
|
for (uint64 mask = 0x8000000000000000; mask; mask >>= 1) {
|
|
|
|
if (mask & exponent) {
|
2016-01-27 00:15:01 +01:00
|
|
|
res *= base;
|
|
|
|
}
|
2017-05-01 03:13:11 +02:00
|
|
|
if (mask != 1) {
|
2016-01-27 00:15:01 +01:00
|
|
|
res *= res;
|
|
|
|
}
|
|
|
|
res %= module;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Computes the inverse of \a number modulo \a module.
|
|
|
|
*/
|
|
|
|
int64 inverseModulo(int64 number, int64 module)
|
|
|
|
{
|
|
|
|
int64 y1 = 0, y2 = 1, tmp;
|
2017-05-01 03:13:11 +02:00
|
|
|
while (number != 1) {
|
2016-01-27 00:15:01 +01:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
uint64 orderModulo(const uint64 number, const uint64 module)
|
|
|
|
{
|
|
|
|
uint64 order = 1;
|
2017-05-01 03:13:11 +02:00
|
|
|
for (; powerModulo(number, order, module) != 1; ++order)
|
|
|
|
;
|
2016-01-27 00:15:01 +01:00
|
|
|
return order;
|
|
|
|
}
|