PrimeModule-ext/main.cpp

100 lines
2.4 KiB
C++
Raw Normal View History

2017-05-06 19:32:27 +02:00
/*
* 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 &parameters)
{
uint64_t what = (int64_t) parameters[0];
uint32_t p;
uint32_t q;
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) {
p = (uint32_t) g;
q = (uint32_t) (what / g);
if (p > q) {
uint32_t tmp = p;
p = q;
q = tmp;
}
Php::Value result;
result[0] = (int32_t) p;
result[1] = (int32_t) q;
return result;
} 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", Php::Type::Numeric),
Php::ByRef("p", Php::Type::Numeric),
Php::ByRef("q", Php::Type::Numeric),
});
return extension;
}
}