mirror of
https://github.com/danog/PrimeModule-ext.git
synced 2024-11-26 20:04:40 +01:00
New C++ header-only library
This commit is contained in:
parent
75f66836d9
commit
420f68e660
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
primemodule
|
||||||
|
103
.vscode/settings.json
vendored
Normal file
103
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"optional": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"__debug": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"__bit_reference": "cpp",
|
||||||
|
"__config": "cpp",
|
||||||
|
"__errc": "cpp",
|
||||||
|
"__functional_base": "cpp",
|
||||||
|
"__hash_table": "cpp",
|
||||||
|
"__locale": "cpp",
|
||||||
|
"__mutex_base": "cpp",
|
||||||
|
"__node_handle": "cpp",
|
||||||
|
"__nullptr": "cpp",
|
||||||
|
"__split_buffer": "cpp",
|
||||||
|
"__string": "cpp",
|
||||||
|
"__threading_support": "cpp",
|
||||||
|
"__tree": "cpp",
|
||||||
|
"__tuple": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"queue": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"shared_mutex": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stack": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"hash_map": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"source_location": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"cfenv": "cpp",
|
||||||
|
"primemodule-ffi.h": "c",
|
||||||
|
"primemodule.h": "c"
|
||||||
|
}
|
||||||
|
}
|
139
Makefile
139
Makefile
@ -1,138 +1,31 @@
|
|||||||
#
|
|
||||||
# Makefile template
|
|
||||||
#
|
|
||||||
# This is an example Makefile that can be used by anyone who is building
|
|
||||||
# his or her own PHP extensions using the PHP-CPP library.
|
|
||||||
#
|
|
||||||
# In the top part of this file we have included variables that can be
|
|
||||||
# altered to fit your configuration, near the bottom the instructions and
|
|
||||||
# dependencies for the compiler are defined. The deeper you get into this
|
|
||||||
# file, the less likely it is that you will have to change anything in it.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Name of your extension
|
|
||||||
#
|
|
||||||
# This is the name of your extension. Based on this extension name, the
|
|
||||||
# name of the library file (name.so) and the name of the config file (name.ini)
|
|
||||||
# are automatically generated
|
|
||||||
#
|
|
||||||
|
|
||||||
NAME = primemodule
|
NAME = primemodule
|
||||||
PHP_CONFIG = php-config
|
|
||||||
|
|
||||||
#
|
BINARY = ${NAME}
|
||||||
# Php.ini directories
|
LIBRARY = lib${NAME}.so
|
||||||
#
|
|
||||||
# In the past, PHP used a single php.ini configuration file. Today, most
|
|
||||||
# PHP installations use a conf.d directory that holds a set of config files,
|
|
||||||
# one for each extension. Use this variable to specify this directory.
|
|
||||||
#
|
|
||||||
# In Ubuntu 14.04 Apache 2.4 is used, which uses the mods-available directory
|
|
||||||
# instead of a conf.d directory. In 16.04 the directory changed yet again.
|
|
||||||
# This has to be checked.
|
|
||||||
#
|
|
||||||
|
|
||||||
INI_DIR = $(shell php --ini | sed '/Scan for additional .ini files in: /!d;s/Scan for additional .ini files in: //')
|
|
||||||
|
|
||||||
#
|
|
||||||
# The extension dirs
|
|
||||||
#
|
|
||||||
# This is normally a directory like /usr/lib/php5/20121221 (based on the
|
|
||||||
# PHP version that you use. We make use of the command line 'php-config'
|
|
||||||
# instruction to find out what the extension directory is, you can override
|
|
||||||
# this with a different fixed directory
|
|
||||||
#
|
|
||||||
|
|
||||||
EXTENSION_DIR = `${PHP_CONFIG} --extension-dir`
|
|
||||||
|
|
||||||
#
|
|
||||||
# The name of the extension and the name of the .ini file
|
|
||||||
#
|
|
||||||
# These two variables are based on the name of the extension. We simply add
|
|
||||||
# a certain extension to them (.so or .ini)
|
|
||||||
#
|
|
||||||
|
|
||||||
EXTENSION = ${NAME}.so
|
|
||||||
INI = ${NAME}.ini
|
|
||||||
|
|
||||||
#
|
|
||||||
# Compiler
|
|
||||||
#
|
|
||||||
# By default, the GNU C++ compiler is used. If you want to use a different
|
|
||||||
# compiler, you can change that here. You can change this for both the
|
|
||||||
# compiler (the program that turns the c++ files into object files) and for
|
|
||||||
# the linker (the program that links all object files into the single .so
|
|
||||||
# library file. By default, g++ (the GNU C++ compiler) is used for both.
|
|
||||||
#
|
|
||||||
|
|
||||||
COMPILER = g++
|
COMPILER = g++
|
||||||
LINKER = g++
|
COMPILER_FLAGS = -Wall -std=c++11 -fpic -finline-functions -ffast-math -O3 -o
|
||||||
|
|
||||||
#
|
|
||||||
# Compiler and linker flags
|
|
||||||
#
|
|
||||||
# This variable holds the flags that are passed to the compiler. By default,
|
|
||||||
# we include the -O2 flag. This flag tells the compiler to optimize the code,
|
|
||||||
# but it makes debugging more difficult. So if you're debugging your application,
|
|
||||||
# you probably want to remove this -O2 flag. At the same time, you can then
|
|
||||||
# add the -g flag to instruct the compiler to include debug information in
|
|
||||||
# the library (but this will make the final libphpcpp.so file much bigger, so
|
|
||||||
# you want to leave that flag out on production servers).
|
|
||||||
#
|
|
||||||
# If your extension depends on other libraries (and it does at least depend on
|
|
||||||
# one: the PHP-CPP library), you should update the LINKER_DEPENDENCIES variable
|
|
||||||
# with a list of all flags that should be passed to the linker.
|
|
||||||
#
|
|
||||||
|
|
||||||
COMPILER_FLAGS = -Wall -c -std=c++11 -fpic -finline-functions -ffast-math -O3 -o
|
|
||||||
LINKER_FLAGS = -shared
|
|
||||||
LINKER_DEPENDENCIES = -lphpcpp
|
|
||||||
|
|
||||||
#
|
|
||||||
# Command to remove files, copy files and create directories.
|
|
||||||
#
|
|
||||||
# I've never encountered a *nix environment in which these commands do not work.
|
|
||||||
# So you can probably leave this as it is
|
|
||||||
#
|
|
||||||
|
|
||||||
RM = rm -f
|
RM = rm -f
|
||||||
CP = cp -f
|
CP = cp
|
||||||
MKDIR = mkdir -p
|
MKDIR = mkdir -p
|
||||||
|
|
||||||
#
|
DESTDIR ?= "/usr"
|
||||||
# All source files are simply all *.cpp files found in the current directory
|
|
||||||
#
|
|
||||||
# A built-in Makefile macro is used to scan the current directory and find
|
|
||||||
# all source files. The object files are all compiled versions of the source
|
|
||||||
# file, with the .cpp extension being replaced by .o.
|
|
||||||
#
|
|
||||||
|
|
||||||
SOURCES = $(wildcard *.cpp)
|
all: ${BINARY} ${LIBRARY}
|
||||||
OBJECTS = $(SOURCES:%.cpp=%.o)
|
|
||||||
|
|
||||||
#
|
${BINARY}: src/main.cpp src/${NAME}.hpp
|
||||||
# From here the build instructions start
|
${COMPILER} ${COMPILER_FLAGS} $@ src/main.cpp
|
||||||
#
|
|
||||||
|
|
||||||
all: ${OBJECTS} ${EXTENSION}
|
${LIBRARY}: src/${NAME}.cpp src/${NAME}.hpp
|
||||||
|
${COMPILER} -shared ${COMPILER_FLAGS} $@ src/${NAME}.cpp
|
||||||
|
|
||||||
${EXTENSION}: ${OBJECTS}
|
install: ${BINARY} ${LIBRARY} src/${NAME}.hpp src/${NAME}.h
|
||||||
${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES}
|
${MKDIR} ${DESTDIR}/bin ${DESTDIR}/lib ${DESTDIR}/include
|
||||||
|
${CP} ${BINARY} ${DESTDIR}/bin
|
||||||
${OBJECTS}:
|
${CP} ${LIBRARY} ${DESTDIR}/lib
|
||||||
${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp}
|
${CP} src/primemodule.hpp src/primemodule.h src/primemodule-ffi.h ${DESTDIR}/include
|
||||||
|
|
||||||
${INI_DIR}:
|
|
||||||
${MKDIR} ${INI_DIR}
|
|
||||||
|
|
||||||
${EXTENSION_DIR}:
|
|
||||||
${MKDIR} ${EXTENSION_DIR}
|
|
||||||
|
|
||||||
install: ${INI_DIR} ${EXTENSION_DIR}
|
|
||||||
${CP} ${EXTENSION} ${EXTENSION_DIR}
|
|
||||||
${CP} ${INI} ${INI_DIR}
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
${RM} ${EXTENSION} ${OBJECTS}
|
${RM} ${BINARY} ${LIBRARY}
|
||||||
|
|
||||||
|
68
README.md
68
README.md
@ -1,43 +1,55 @@
|
|||||||
# PrimeModule-ext
|
# PrimeModule-ext
|
||||||
|
|
||||||
PHP extension for factorizing huge (up to 2^63-1) numbers (optimized for huge semiprimes).
|
C++ header-only library, binary and FFI library for factorizing huge (up to 2^63-1) numbers (optimized for huge semiprimes).
|
||||||
|
|
||||||
To compile it, simply install https://github.com/CopernicaMarketingSoftware/PHP-CPP and run `make && sudo make install` in this directory.
|
## Install
|
||||||
|
|
||||||
```
|
Arch Linux (AUR):
|
||||||
sudo apt-get install build-essential php$(echo "<?php echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;" | php)-dev && git clone https://github.com/danog/PHP-CPP && cd PHP-CPP && make -j$(nproc) && sudo make install && cd .. && git clone https://github.com/danog/PrimeModule-ext && cd PrimeModule-ext && make -j$(nproc) && sudo make install
|
```bash
|
||||||
|
paru -S primemodule
|
||||||
```
|
```
|
||||||
|
|
||||||
API:
|
Debian/Ubuntu:
|
||||||
|
|
||||||
```
|
```
|
||||||
integer factorize( mixed $pq )
|
sudo apt-get install build-essential && git clone https://github.com/danog/PrimeModule-ext && cd PrimeModule-ext && make -j$(nproc) && sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameters:
|
## API
|
||||||
|
|
||||||
pq - The number to factorize, a string or an integer.
|
### Binary
|
||||||
|
|
||||||
|
```bash
|
||||||
Return value: an integer, containing one of the factors of the number.
|
primemodule number
|
||||||
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
On success (return code 0), prints to stdout one of the prime factors of `number`.
|
||||||
|
|
||||||
|
### C++
|
||||||
|
|
||||||
|
```c++
|
||||||
|
uint32_t PrimeModule::factorize(uint64_t number);
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns one of the prime factors of `number`, throws an std::runtime_error on failure.
|
||||||
|
|
||||||
|
### C
|
||||||
|
|
||||||
|
```c
|
||||||
|
int64_t factorize(uint64_t number);
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns one of the prime factors of `number`, returns -1 on failure.
|
||||||
|
|
||||||
|
|
||||||
|
### PHP
|
||||||
|
|
||||||
|
```php
|
||||||
<?php
|
<?php
|
||||||
var_dump(factorize(1724114033281923457));
|
|
||||||
var_dump(factorize("2189285106422392999"));
|
$f = FFI::load("/usr/include/primemodule-ffi.h");
|
||||||
var_dump(factorize(15));
|
|
||||||
|
// Always pass strings to allow 64-bit factorization with no loss of precision on 32-bit PHP.
|
||||||
|
var_dump($f->factorizeFFI("2189285106422392999"));
|
||||||
```
|
```
|
||||||
|
|
||||||
This will output:
|
Returns one of the prime factors of `2189285106422392999`, returns -1 on failure.
|
||||||
|
|
||||||
```
|
|
||||||
int(1402015859)
|
|
||||||
int(1117663223)
|
|
||||||
int(5)
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see, the factorize function accepts integers and strings as parameter, so that if you're poor and you have only a 32 bit system, you will still be able to provide 64 bit integers as a string.
|
|
||||||
|
|
||||||
The function can throw an \Exception if factorization fails.
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
<?php
|
|
||||||
var_dump(factorize(2189285106422392999));
|
|
||||||
var_dump(factorize("2189285106422392999"));
|
|
||||||
var_dump(factorize(15));
|
|
8
examples/example.c
Normal file
8
examples/example.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include <primemodule.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Compile with -lprimemodule
|
||||||
|
int main() {
|
||||||
|
printf("%ld\n", factorize(2189285106422392999));
|
||||||
|
}
|
6
examples/example.cpp
Normal file
6
examples/example.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <primemodule.hpp>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << PrimeModule::factorize(2189285106422392999) << std::endl;
|
||||||
|
}
|
6
examples/example.php
Normal file
6
examples/example.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$f = FFI::load("/usr/include/primemodule-ffi.h");
|
||||||
|
|
||||||
|
// Always pass strings to allow 64-bit factorization with no loss of precision on 32-bit PHP.
|
||||||
|
var_dump($f->factorizeFFI("2189285106422392999"));
|
3
examples/example.sh
Executable file
3
examples/example.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
primemodule 2189285106422392999
|
85
main.cpp
85
main.cpp
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
extension=primemodule.so
|
|
32
src/main.cpp
Normal file
32
src/main.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "primemodule.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "PrimeModule: extremely fast 64-bit factorization module." << std::endl
|
||||||
|
<< "Copyright (C) 2015-2021 Nikolai Kudashov, Daniil Gentili" << std::endl
|
||||||
|
<< "Licensed under GPLv2" << std::endl
|
||||||
|
<< "https://github.com/danog/PrimeModule-ext" << std::endl
|
||||||
|
<< std::endl << "Usage: " << argv[0] << " number" << std::endl
|
||||||
|
<< std::endl << "One of the prime factors will be printed to stdout." << std::endl
|
||||||
|
<< std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint64_t what;
|
||||||
|
try {
|
||||||
|
what = std::stoull(argv[1]);
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "An invalid 64-bit integer was provided!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint32_t res;
|
||||||
|
try {
|
||||||
|
res = PrimeModule::factorize(what);
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "An error occurred during factorization!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::cout << res << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
5
src/primemodule-ffi.h
Normal file
5
src/primemodule-ffi.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#define FFI_SCOPE "primemodule"
|
||||||
|
#define FFI_LIB "libprimemodule.so"
|
||||||
|
|
||||||
|
// Returns at most a 32-bit signed int or -1
|
||||||
|
int32_t factorizeFFI(const char *number);
|
27
src/primemodule.cpp
Normal file
27
src/primemodule.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 "primemodule.h"
|
||||||
|
#include "primemodule.hpp"
|
||||||
|
|
||||||
|
extern "C" int64_t factorize(uint64_t number)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return PrimeModule::factorize(number);
|
||||||
|
} catch (...) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extern "C" int32_t factorizeFFI(const char *number)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return PrimeModule::factorize(std::stoull(number));
|
||||||
|
} catch (...) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
5
src/primemodule.h
Normal file
5
src/primemodule.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Returns at most a 32-bit unsigned int or -1
|
||||||
|
extern "C" int64_t factorize(uint64_t number);
|
77
src/primemodule.hpp
Normal file
77
src/primemodule.hpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* 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 <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace PrimeModule {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Factorize the provided semiprime, throws an std::runtime_error on failure
|
||||||
|
uint32_t factorize(uint64_t number) {
|
||||||
|
int32_t it = 0, i, j;
|
||||||
|
uint64_t g = 0;
|
||||||
|
for (i = 0; i < 3 || it < 1000; i++) {
|
||||||
|
uint64_t t = ((lrand48() & 15) + 17) % number;
|
||||||
|
uint64_t x = (long long)lrand48() % (number - 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 >= number) {
|
||||||
|
c -= number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a += a;
|
||||||
|
if (a >= number) {
|
||||||
|
a -= number;
|
||||||
|
}
|
||||||
|
b >>= 1;
|
||||||
|
}
|
||||||
|
x = c;
|
||||||
|
uint64_t z = x < y ? number + x - y : x - y;
|
||||||
|
g = PrimeModule::gcd(z, number);
|
||||||
|
if (g != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(j & (j - 1))) {
|
||||||
|
y = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g > 1 && g < number) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g > 1 && g < number) {
|
||||||
|
return (uint32_t)g;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Factorization failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user