Skip to content

Commit 7945474

Browse files
authored
Merge branch 'main' into msys2
2 parents 641bd56 + 93c6062 commit 7945474

File tree

12 files changed

+1185
-731
lines changed

12 files changed

+1185
-731
lines changed

README.md

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -231,29 +231,34 @@ ECM on Mersenne numbers
231231
------------------------
232232
ECM is a probabilistic generalization of P−1/P+1: it succeeds when the group order on a random curve has a cofactor that’s B1,B2-smooth, so B1/B2 should be chosen for the target factor size.
233233

234-
ECM on Mersenne numbers N = 2^p - 1. Stage 1 multiplies by all prime powers <= B1; Stage 2 scans primes in (B1, B2]. Without flags you get the plain prime-by-prime Stage 2. "-brent d" enables a simplified Brent-Suyama extension by using q^d (a bit more extra reach beyond B2). "-bsgs" batches several multipliers into one ladder call to reduce overhead. Both flags are complementary and can be combined. You can pass pre-known factors via "-factors <list>" (decimal or 0x hex); they are divided out (with multiplicities) before ECM. For p=701, 796337 is a known factor. Runs are checkpointed periodically; re-running the same command resumes safely.
235-
```
236-
# Plain ECM on M_p (here p=701)
237-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8
238-
239-
# ECM + batching only (same primes, fewer ladder calls)
240-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -bsgs
241-
242-
# ECM + simplified Brent-Suyama only (q -> q^3 here)
243-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -brent 3
244-
245-
# ECM + both (complementary: q -> q^3 and batched multipliers)
246-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -brent 3 -bsgs
247-
248-
# Provide known factors (e.g., for p=701, factor 796337)
249-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -factors 796337
250-
251-
# Combine known factors with brent+bsgs
252-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -brent 3 -bsgs -factors 796337
253-
254-
# Resume after interrupt (same command; auto-checkpointed)
255-
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8 -brent 3 -bsgs -factors 796337
256-
```
234+
ECM on Mersenne numbers
235+
-----------------------
236+
ECM on N = 2^p - 1.
237+
238+
Curve model and torsion:
239+
- default: Edwards, torsion 8
240+
- -montgomery: use Montgomery model
241+
- -torsion16: force torsion 16
242+
- -notorsion: no torsion
243+
244+
Outputs:
245+
- results append to ecm_result.json
246+
- last curve saved to lastcurve.gp (PARI/GP)
247+
- checkpoints auto-resume on re-run
248+
249+
Examples:
250+
# Stage-1 only
251+
./prmers 701 -ecm -b1 6000 -K 8
252+
253+
# Enable Stage-2
254+
./prmers 701 -ecm -b1 6000 -b2 33333 -K 8
255+
256+
# Model / torsion variants
257+
./prmers 701 -ecm -b1 6000 -K 8 -montgomery
258+
./prmers 701 -ecm -b1 6000 -K 8 -torsion16
259+
./prmers 701 -ecm -b1 6000 -K 8 -notorsion
260+
./prmers 701 -ecm -b1 6000 -K 8 -montgomery -torsion16
261+
./prmers 701 -ecm -b1 6000 -K 8 -montgomery -notorsion
257262

258263

259264
## GPU Memory Test (`-memtest`)

docs/ecm_benchmark.txt

Lines changed: 226 additions & 0 deletions
Large diffs are not rendered by default.

include/core/Version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <string>
55

66
namespace core {
7-
const std::string PRMERS_VERSION = "4.15.03-alpha";
7+
const std::string PRMERS_VERSION = "4.15.13-alpha";
88
} // namespace core
99

1010
#endif // VERSION_HPP

include/io/CliParser.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct CliOptions {
3434
uint64_t gerbicz_error_count = 0;
3535
uint64_t erroriter = 0;
3636
bool proof = true;
37+
bool edwards = true;
38+
bool torsion16 = false;
39+
bool notorsion = false;
40+
uint64_t sigma = 0ULL;
41+
uint64_t seed = 0ULL;
3742
bool resume = true;
3843
bool submit = false;
3944
uint64_t chunk256 = 4;
@@ -66,6 +71,9 @@ struct CliOptions {
6671
std::string osVersion = "14.0";
6772
std::string osArch = "x86_64";
6873
std::string aid = "";
74+
std::string sigma_hex = "";
75+
uint64_t curve_seed = 0ULL;
76+
uint64_t base_seed = 0ULL;
6977
std::string uid = "";
7078
int res64_display_interval = 0;
7179
bool cl_queue_throttle_active = false;
@@ -75,6 +83,7 @@ struct CliOptions {
7583
std::string http_host = "localhost";
7684
bool ipv4 = true;
7785
uint64_t max_e_bits = 268'435'456ULL;
86+
uint64_t curves_tested_for_found = 0;
7887

7988
};
8089

include/io/WorktodoParser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ struct WorktodoEntry {
1111
bool prpTest = false;
1212
bool llTest = false;
1313
bool pm1Test = false;
14+
bool ecmTest = false;
1415
uint32_t exponent = 0;
1516
std::string aid;
1617
std::string rawLine;
1718
std::vector<std::string> knownFactors;
1819
uint32_t residueType = 1;
1920
uint64_t B1 = 0;
2021
uint64_t B2 = 0;
22+
uint64_t curves = 0;
2123
};
2224

2325
class WorktodoParser {

src/core/App.cpp

Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -253,50 +253,63 @@ App::App(int argc, char** argv)
253253
: argc_(argc)
254254
, argv_(argv)
255255
,options([&]{
256-
std::vector<std::string> merged;
257-
merged.push_back(argv[0]);
258-
for (int i = 1; i < argc; ++i) {
259-
if (std::strcmp(argv[i], "-config") == 0 && i+1 < argc) {
260-
auto cfg_args = parseConfigFile(argv[i+1]);
261-
merged.insert(merged.end(), cfg_args.begin(), cfg_args.end());
262-
i++;
263-
} else {
264-
merged.emplace_back(argv[i]);
265-
}
266-
}
267-
268-
std::vector<char*> c_argv;
269-
for (auto& s : merged)
270-
c_argv.push_back(const_cast<char*>(s.c_str()));
271-
c_argv.push_back(nullptr);
272-
auto o = io::CliParser::parse(static_cast<int>(merged.size()), c_argv.data());
273-
274-
io::WorktodoParser wp{o.worktodo_path};
275-
if (auto e = wp.parse()) {
276-
o.exponent = e->exponent;
277-
o.mode = e->prpTest ? "prp" : (e->llTest ? "ll" : (e->pm1Test ? "pm1" : ""));
278-
o.aid = e->aid;
279-
o.knownFactors = e->knownFactors;
280-
if (e->pm1Test) {
281-
o.B1 = e->B1;
282-
o.B2 = e->B2;
283-
}
284-
hasWorktodoEntry_ = true;
285-
}
286-
287-
if (!hasWorktodoEntry_ && o.exponent == 0) {
288-
std::cerr << "Error: no valid entry in "
289-
<< options.worktodo_path
290-
<< " and no exponent provided on the command line\n";
291-
292-
293-
if (!options.gui) {
294-
o.exponent = static_cast<uint64_t>(askExponentInteractively());
256+
std::vector<std::string> merged;
257+
merged.push_back(argv[0]);
258+
for (int i = 1; i < argc; ++i) {
259+
if (std::strcmp(argv[i], "-config") == 0 && i+1 < argc) {
260+
auto cfg_args = parseConfigFile(argv[i+1]);
261+
merged.insert(merged.end(), cfg_args.begin(), cfg_args.end());
262+
i++;
263+
} else {
264+
merged.emplace_back(argv[i]);
295265
}
296-
o.mode = "prp";
297-
//std::exit(-1);
298-
}
299-
return o;
266+
}
267+
268+
std::vector<char*> c_argv;
269+
for (auto& s : merged)
270+
c_argv.push_back(const_cast<char*>(s.c_str()));
271+
c_argv.push_back(nullptr);
272+
auto o = io::CliParser::parse(static_cast<int>(merged.size()), c_argv.data());
273+
274+
io::WorktodoParser wp{o.worktodo_path};
275+
if (auto e = wp.parse()) {
276+
o.exponent = e->exponent;
277+
o.mode = e->ecmTest ? "ecm"
278+
: (e->prpTest ? "prp"
279+
: (e->llTest ? "ll"
280+
: (e->pm1Test ? "pm1" : "")));
281+
o.aid = e->aid;
282+
o.knownFactors = e->knownFactors;
283+
284+
if (e->pm1Test) {
285+
o.B1 = e->B1;
286+
o.B2 = e->B2;
287+
}
288+
289+
if (e->ecmTest) {
290+
o.B1 = e->B1;
291+
o.B2 = e->B2;
292+
o.nmax = e->curves;
293+
o.K = e->curves;
294+
}
295+
296+
hasWorktodoEntry_ = true;
297+
}
298+
299+
300+
if (!hasWorktodoEntry_ && o.exponent == 0) {
301+
std::cerr << "Error: no valid entry in "
302+
<< options.worktodo_path
303+
<< " and no exponent provided on the command line\n";
304+
305+
306+
if (!options.gui) {
307+
o.exponent = static_cast<uint64_t>(askExponentInteractively());
308+
}
309+
o.mode = "prp";
310+
//std::exit(-1);
311+
}
312+
return o;
300313
}())
301314
, context(options.device_id,
302315
static_cast<std::size_t>(options.enqueue_max),
@@ -819,7 +832,7 @@ int App::run() {
819832
bool haveS1 = File(s1f).exists() || File(s1f + ".old").exists();
820833
bool haveS2 = File(s2f).exists() || File(s2f + ".old").exists() || File(s2f + ".new").exists();
821834

822-
if ((haveS2 || haveS1) && options.nmax == 0 && options.K == 0) {
835+
if ((haveS2) && options.nmax == 0 && options.K == 0) {
823836
std::ostringstream msg;
824837
msg << "Detected P-1 checkpoint(s): "
825838
<< (haveS2 ? "[Stage 2] " : "")
@@ -831,6 +844,14 @@ int App::run() {
831844
rc_local = runPM1Stage2Marin();
832845
ran_local = true;
833846
} else {
847+
if(haveS1){
848+
std::ostringstream msg;
849+
msg << "Detected P-1 checkpoint(s): "
850+
<< (haveS2 ? "[Stage 2] " : "")
851+
<< (haveS1 ? "[Stage 1] " : "")
852+
<< "→ jumping to Stage1()";
853+
std::cout << msg.str() << std::endl;
854+
}
834855
std::string msg = "No P-1 checkpoints found → running Stage 1 (runPM1Marin)";
835856
std::cout << msg << std::endl;
836857
if (guiServer_) { guiServer_->appendLog(msg); guiServer_->setStatus("Running P-1 Stage 1"); }

src/io/CliParser.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,12 @@ void printUsage(const char* progName) {
8282
std::cout << " -checklevel <value> : (Optional) Will force gerbicz check every B*<value> by default check is done every 10 min and at the end." << std::endl;
8383
std::cout << " -wagstaff : (Optional) will check PRP if (2^p + 1)/3 is probably prime" << std::endl;
8484
std::cout << " -ecm -b1 <B1> [-b2 <B2>] -K <curves> : Run ECM factoring with bounds B1 [and optional B2], on given number of curves" << std::endl;
85-
std::cout << " -brent [<d>] : (Optional) use Brent-Suyama variant with default or specified degree d (e.g., -brent 6)" << std::endl;
86-
std::cout << " -bsgs : (Optional) enable batching of multipliers in ECM stage 2 to reduce ladder calls" << std::endl;
85+
std::cout << " -montgomery : (Optional) use Montgomery instead of twisted Edwards curve" << std::endl;
86+
std::cout << " -edwards : (Optional) use twisted Edwards curve" << std::endl;
87+
std::cout << " -torsion16 : (Optional) use torsion-16 instead of default torsion-8" << std::endl;
88+
std::cout << " -notorsion : (Optional) use no torsion instead of default torsion-8" << std::endl;
89+
//std::cout << " -brent [<d>] : (Optional) use Brent-Suyama variant with default or specified degree d (e.g., -brent 6)" << std::endl;
90+
//std::cout << " -bsgs : (Optional) enable batching of multipliers in ECM stage 2 to reduce ladder calls" << std::endl;
8791
std::cout << " -marin : (Optional) deactivate use of marin backend" << std::endl;
8892
std::cout << " -resume : (Optional) write GMP-ECM and Prime 95 resume file after P-1 stage 1" << std::endl;
8993
//std::cout << " -p95 : (Optional) write Prime 95 resume file after P-1 stage 1" << std::endl;
@@ -188,6 +192,18 @@ CliOptions CliParser::parse(int argc, char** argv ) {
188192
else if (std::strcmp(argv[i], "-marin") == 0) {
189193
opts.marin = false;
190194
}
195+
else if (std::strcmp(argv[i], "-montgomery") == 0) {
196+
opts.edwards = false;
197+
}
198+
else if (std::strcmp(argv[i], "-edwards") == 0) {
199+
opts.edwards = true;
200+
}
201+
else if (std::strcmp(argv[i], "-torsion16") == 0) {
202+
opts.torsion16 = true;
203+
}
204+
else if (std::strcmp(argv[i], "-notorsion") == 0) {
205+
opts.notorsion = true;
206+
}
191207
else if (std::strcmp(argv[i], "-submit") == 0) {
192208
opts.submit = true;
193209
}

0 commit comments

Comments
 (0)