FindAFactor 3.9.0__tar.gz → 4.0.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- findafactor-4.0.0/FindAFactor/__init__.py +1 -0
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor/find_a_factor.py +13 -7
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor.egg-info/PKG-INFO +1 -1
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor.egg-info/SOURCES.txt +0 -3
- {findafactor-3.9.0 → findafactor-4.0.0}/PKG-INFO +1 -1
- {findafactor-3.9.0 → findafactor-4.0.0}/README.md +8 -10
- {findafactor-3.9.0 → findafactor-4.0.0}/pyproject.toml +3 -7
- {findafactor-3.9.0 → findafactor-4.0.0}/setup.py +1 -1
- findafactor-3.9.0/FindAFactor/__init__.py +0 -1
- findafactor-3.9.0/FindAFactor/_find_a_factor.cpp +0 -1309
- findafactor-3.9.0/FindAFactor/dispatchqueue.cpp +0 -121
- findafactor-3.9.0/FindAFactor/oclengine.cpp +0 -386
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor.egg-info/dependency_links.txt +0 -0
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor.egg-info/not-zip-safe +0 -0
- {findafactor-3.9.0 → findafactor-4.0.0}/FindAFactor.egg-info/top_level.txt +0 -0
- {findafactor-3.9.0 → findafactor-4.0.0}/LICENSE +0 -0
- {findafactor-3.9.0 → findafactor-4.0.0}/setup.cfg +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
from .find_a_factor import find_a_factor, FactoringMethod
|
@@ -1,19 +1,25 @@
|
|
1
1
|
import os
|
2
2
|
import _find_a_factor
|
3
|
+
from enum import IntEnum
|
4
|
+
|
5
|
+
|
6
|
+
class FactoringMethod(IntEnum):
|
7
|
+
PRIME_SOLVER = 0
|
8
|
+
MIXED = 1
|
9
|
+
FACTOR_FINDER = 2
|
10
|
+
|
3
11
|
|
4
12
|
def find_a_factor(n,
|
5
|
-
|
6
|
-
use_gaussian_elimination=True if os.environ.get('FINDAFACTOR_USE_GAUSSIAN_ELIMINATION') else False,
|
13
|
+
method=FactoringMethod(int(os.environ.get('FINDAFACTOR_METHOD'))) if os.environ.get('FINDAFACTOR_METHOD') else FactoringMethod.PRIME_SOLVER,
|
7
14
|
node_count=int(os.environ.get('FINDAFACTOR_NODE_COUNT')) if os.environ.get('FINDAFACTOR_NODE_COUNT') else 1,
|
8
15
|
node_id=int(os.environ.get('FINDAFACTOR_NODE_ID')) if os.environ.get('FINDAFACTOR_NODE_ID') else 0,
|
9
16
|
trial_division_level=int(os.environ.get('FINDAFACTOR_TRIAL_DIVISION_LEVEL')) if os.environ.get('FINDAFACTOR_TRIAL_DIVISION_LEVEL') else (1<<20),
|
10
|
-
gear_factorization_level=int(os.environ.get('FINDAFACTOR_GEAR_FACTORIZATION_LEVEL')) if os.environ.get('FINDAFACTOR_GEAR_FACTORIZATION_LEVEL') else
|
11
|
-
wheel_factorization_level=int(os.environ.get('FINDAFACTOR_WHEEL_FACTORIZATION_LEVEL')) if os.environ.get('FINDAFACTOR_WHEEL_FACTORIZATION_LEVEL') else
|
17
|
+
gear_factorization_level=int(os.environ.get('FINDAFACTOR_GEAR_FACTORIZATION_LEVEL')) if os.environ.get('FINDAFACTOR_GEAR_FACTORIZATION_LEVEL') else 13,
|
18
|
+
wheel_factorization_level=int(os.environ.get('FINDAFACTOR_WHEEL_FACTORIZATION_LEVEL')) if os.environ.get('FINDAFACTOR_WHEEL_FACTORIZATION_LEVEL') else 11,
|
12
19
|
smoothness_bound_multiplier=float(os.environ.get('FINDAFACTOR_SMOOTHNESS_BOUND_MULTIPLIER')) if os.environ.get('FINDAFACTOR_SMOOTHNESS_BOUND_MULTIPLIER') else 1.0,
|
13
|
-
batch_size_multiplier=float(os.environ.get('FINDAFACTOR_BATCH_SIZE_MULTIPLIER')) if os.environ.get('FINDAFACTOR_BATCH_SIZE_MULTIPLIER') else
|
20
|
+
batch_size_multiplier=float(os.environ.get('FINDAFACTOR_BATCH_SIZE_MULTIPLIER')) if os.environ.get('FINDAFACTOR_BATCH_SIZE_MULTIPLIER') else 128.0):
|
14
21
|
return int(_find_a_factor._find_a_factor(str(n),
|
15
|
-
|
16
|
-
use_gaussian_elimination,
|
22
|
+
int(method),
|
17
23
|
node_count, node_id,
|
18
24
|
trial_division_level,
|
19
25
|
gear_factorization_level,
|
@@ -3,10 +3,7 @@ README.md
|
|
3
3
|
pyproject.toml
|
4
4
|
setup.py
|
5
5
|
FindAFactor/__init__.py
|
6
|
-
FindAFactor/_find_a_factor.cpp
|
7
|
-
FindAFactor/dispatchqueue.cpp
|
8
6
|
FindAFactor/find_a_factor.py
|
9
|
-
FindAFactor/oclengine.cpp
|
10
7
|
FindAFactor.egg-info/PKG-INFO
|
11
8
|
FindAFactor.egg-info/SOURCES.txt
|
12
9
|
FindAFactor.egg-info/dependency_links.txt
|
@@ -21,34 +21,32 @@ Windows users might find Windows Subsystem Linux (WSL) to be the easier and pref
|
|
21
21
|
## Usage
|
22
22
|
|
23
23
|
```py
|
24
|
-
from FindAFactor import find_a_factor
|
24
|
+
from FindAFactor import find_a_factor, FactoringMethod
|
25
25
|
|
26
26
|
to_factor = 1000
|
27
27
|
|
28
28
|
factor = find_a_factor(
|
29
29
|
to_factor,
|
30
|
-
|
31
|
-
use_gaussian_elimination=False,
|
30
|
+
method=FactoringMethod.PRIME_SOLVER,
|
32
31
|
node_count=1, node_id=0,
|
33
32
|
trial_division_level=2**20,
|
34
|
-
gear_factorization_level=
|
33
|
+
gear_factorization_level=13,
|
35
34
|
wheel_factorization_level=11,
|
36
35
|
smoothness_bound_multiplier=1.0,
|
37
|
-
batch_size_multiplier=
|
36
|
+
batch_size_multiplier=128.0
|
38
37
|
)
|
39
38
|
```
|
40
39
|
|
41
40
|
The `find_a_factor()` function should return any nontrivial factor of `to_factor` (that is, any factor besides `1` or `to_factor`) if it exists. If a nontrivial factor does _not_ exist (i.e., the number to factor is prime), the function will return `1` or the original `to_factor`.
|
42
41
|
|
43
|
-
- `
|
44
|
-
- `use_gaussian_elimination` (default value: `False`): This option is only relevant if `use_congruence_of_squares=True`. In that case, if `use_gaussian_elimination` is `True`, then proper Gaussian elimination is used, with **O(N^3)** worst case complexity but using potentially much smaller "N" count of rows. If the option is `False`, rather than Gaussian elimination, the algorithm checks only for exact factorization parity duplicates in the "smooth" number rows, for **O(N^2)** worst case complexity, but using a potentially much larger "N" count of rows.
|
42
|
+
- `method` (default value: `PRIME_SOLVER`/`0`): `PRIME_SOLVER`/`0` will prove that a number is prime (by failing to find any factors with wheel and gear factorization). `FACTOR_SOLVER`/`2` is optimized for the assumption that the number has at least two nontrivial factors. (`FACTOR_SOLVER`/`2` is not yet implemented, but this is the next development goal.) `MIXED`/`1` will be able to demonstrate that a number is prime, if necessary, while imitating some of the optimized behavior of `FACTOR_SOLVER`/`2`.
|
45
43
|
- `node_count` (default value: `1`): `FindAFactor` can perform factorization in a _distributed_ manner, across nodes, without network communication! When `node_count` is set higher than `1`, the search space for factors is segmented equally per node. If the number to factor is semiprime, and brute-force search is used instead of congruence of squares, for example, all nodes except the one that happens to contain the (unknown) prime factor less than the square root of `to_factor` will ultimately return `1`, while one node will find and return this factor. For best performance, every node involved in factorization should have roughly the same CPU throughput capacity.
|
46
44
|
- `node_id` (default value: `0`): This is the identifier of this node, when performing distributed factorization with `node_count` higher than `1`. `node_id` values start at `0` and go as high as `(node_count - 1)`.
|
47
45
|
- `trial_division_level` (default value: `2**20`): Trial division is carried out as a preliminary round for all primes up this number. If you need more primes for your smoothness bound, increase this level.
|
48
|
-
- `gear_factorization_level` (default value: `
|
46
|
+
- `gear_factorization_level` (default value: `13`): This is the value up to which "wheel (and gear) factorization" and trial division are used to check factors and optimize "brute force," in general. The default value of `13` includes all prime factors of `13` and below and works well for `use_congruence_of_squares=True`, though significantly higher might be preferred in certain cases.
|
49
47
|
- `wheel_factorization_level` (default value: `11`): "Wheel" vs. "gear" factorization balances two types of factorization wheel ("wheel" vs. "gear" design) that often work best when the "wheel" is only a few prime number levels lower than gear factorization. Optimized implementation for wheels is only available up to `13`. The primes above "wheel" level, up to "gear" level, are the primes used specifically for "gear" factorization.
|
50
|
-
- `smoothness_bound_multiplier` (default value: `1.0`): starting with the first prime number after wheel factorization, the congruence of squares approach (with Quadratic Sieve)
|
51
|
-
- `batch_size_multiplier` (default value: `
|
48
|
+
- `smoothness_bound_multiplier` (default value: `1.0`): starting with the first prime number after wheel factorization, the congruence of squares approach (with Quadratic Sieve) has a "smoothness bound" unit with as many distinct prime numbers as bits in the number to facto0r (for argument of `1.0` multiplier). To increase or decrease this number, consider it multiplied by the value of `smoothness_bound_multiplier`.
|
49
|
+
- `batch_size_multiplier` (default value: `128.0`): Each `1.0` increment of the multiplier is 2 cycles of gear and wheel factorization, alternating every other cycle between bottom of guessing range and top of guessing range, for every thread in use.
|
52
50
|
|
53
51
|
All variables defaults can also be controlled by environment variables:
|
54
52
|
- `FINDAFACTOR_USE_CONGRUENCE_OF_SQUARES` (any value makes `True`, while default is `False`)
|
@@ -2,17 +2,13 @@
|
|
2
2
|
requires = [
|
3
3
|
"cmake",
|
4
4
|
"pybind11",
|
5
|
-
"setuptools"
|
6
|
-
"scikit-build"
|
5
|
+
"setuptools"
|
7
6
|
]
|
8
|
-
build-backend = "
|
9
|
-
|
10
|
-
[tool.scikit-build]
|
11
|
-
cmake.args = ["-DCMAKE_BUILD_TYPE=Release"]
|
7
|
+
build-backend = "setuptools.build_meta"
|
12
8
|
|
13
9
|
[project]
|
14
10
|
name = "FindAFactor"
|
15
|
-
version = "
|
11
|
+
version = "4.0.0"
|
16
12
|
requires-python = ">=3.8"
|
17
13
|
description = "Find any nontrivial factor of a number"
|
18
14
|
readme = {file = "README.txt", content-type = "text/markdown"}
|
@@ -1 +0,0 @@
|
|
1
|
-
from .find_a_factor import find_a_factor
|