mirror of
https://github.com/danog/PrimeModule-ext.git
synced 2024-11-30 04:19:18 +01:00
86 lines
2.0 KiB
C++
86 lines
2.0 KiB
C++
/*
|
|
* This taken from the source code of tgnet library v. 1.0
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Nikolai Kudashov, 2015.
|
|
*/
|
|
|
|
#include <phpcpp.h>
|
|
|
|
|
|
inline uint64_t gcd(uint64_t a, uint64_t b) {
|
|
while (a != 0 && b != 0) {
|
|
while ((b & 1) == 0) {
|
|
b >>= 1;
|
|
}
|
|
while ((a & 1) == 0) {
|
|
a >>= 1;
|
|
}
|
|
if (a > b) {
|
|
a -= b;
|
|
} else {
|
|
b -= a;
|
|
}
|
|
}
|
|
return b == 0 ? a : b;
|
|
}
|
|
inline Php::Value factorize(Php::Parameters ¶meters)
|
|
{
|
|
uint64_t what = (int64_t) parameters[0];
|
|
int32_t it = 0, i, j;
|
|
uint64_t g = 0;
|
|
for (i = 0; i < 3 || it < 1000; i++) {
|
|
uint64_t t = ((lrand48() & 15) + 17) % what;
|
|
uint64_t x = (long long) lrand48() % (what - 1) + 1, y = x;
|
|
int32_t lim = 1 << (i + 18);
|
|
for (j = 1; j < lim; j++) {
|
|
++it;
|
|
uint64_t a = x, b = x, c = t;
|
|
while (b) {
|
|
if (b & 1) {
|
|
c += a;
|
|
if (c >= what) {
|
|
c -= what;
|
|
}
|
|
}
|
|
a += a;
|
|
if (a >= what) {
|
|
a -= what;
|
|
}
|
|
b >>= 1;
|
|
}
|
|
x = c;
|
|
uint64_t z = x < y ? what + x - y : x - y;
|
|
g = gcd(z, what);
|
|
if (g != 1) {
|
|
break;
|
|
}
|
|
if (!(j & (j - 1))) {
|
|
y = x;
|
|
}
|
|
}
|
|
if (g > 1 && g < what) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (g > 1 && g < what) {
|
|
return (int32_t) g;
|
|
} else {
|
|
throw Php::Exception("Factorization failed!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
extern "C" {
|
|
PHPCPP_EXPORT void *get_module() {
|
|
static Php::Extension extension("primemodule", "1.0");
|
|
extension.add<factorize>("factorize", {
|
|
Php::ByVal("pq")
|
|
});
|
|
return extension;
|
|
}
|
|
}
|
|
|