From 787c08befdb85ad8f21b4ce27acca3ab268d7916 Mon Sep 17 00:00:00 2001 From: DemIS-1 <46573498+DemIS-1@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:47:21 +0300 Subject: [PATCH] Correct FMT for Cygwin Also added check for input values D(n,k) if not digit. --- coul.c | 85 ++++++++++++++++++------- read-line-coded.txt | 140 +++++++++++++++++++++++++++++++++++++++++ read-line-generate.bat | 3 + read-line-generate.sh | 5 ++ read-line.txt | 140 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 350 insertions(+), 23 deletions(-) create mode 100644 read-line-coded.txt create mode 100644 read-line-generate.bat create mode 100644 read-line-generate.sh create mode 100644 read-line.txt diff --git a/coul.c b/coul.c index d485e76..2b060d4 100644 --- a/coul.c +++ b/coul.c @@ -1,6 +1,12 @@ /* needed on FreeBSD for getline() to be exported from stdio.h */ #define _WITH_GETLINE +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_RESET "\x1b[0m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" + #include #include #include @@ -12,7 +18,11 @@ # include #endif #include +#ifdef __CYGWIN__ +/* noop */ +#else #include +#endif #include #include @@ -142,9 +152,12 @@ uint nsprimes; double t0 = 0; struct rusage rusage_buf; static inline double utime(void) { +#ifdef __CYGWIN__ + return clock() / 1000; +#else getrusage(RUSAGE_SELF, &rusage_buf); - return (double)rusage_buf.ru_utime.tv_sec - + (double)rusage_buf.ru_utime.tv_usec / 1000000; + return (double)rusage_buf.ru_utime.tv_sec + (double)rusage_buf.ru_utime.tv_usec / 1000000; +#endif } timer_t diag_timerid, log_timerid; volatile bool need_work, need_diag, need_log; @@ -261,7 +274,7 @@ void update_window(t_level *cur_level) { uint this_batch = (opt_batch_min < 0) ? batch_alloc : batch_alloc - 1; printf("\x1b]0;b%d:", this_batch); uint pc = 0; - for (uint i = 1; i < cur_level->level && pc < 3; ++i) { + for (uint i = 1; i <= cur_level->level && pc < 3; ++i) { if (levels[i].is_forced) continue; printf(" %lu", levels[i].p); @@ -317,6 +330,7 @@ void report(char *format, ...) { gmp_vfprintf(rfp, format, ap); va_end(ap); fflush(rfp); + t0 = utime(); } } @@ -734,6 +748,7 @@ void recover(FILE *fp) { char *curbuf = NULL; size_t len = 120, len305 = 0, len202 = 0; + fseek(fp, 0L, SEEK_SET); while (1) { ssize_t nread = getline(&curbuf, &len, fp); if (nread <= 0) { @@ -782,10 +797,12 @@ void recover(FILE *fp) { else fail("unexpected log line %.3s in %s", curbuf, rpath); } + fseek(fp, 0L, SEEK_END); if (improve_max && seen_best && mpz_cmp(best, max) < 0) mpz_set(max, best); if (last305) parse_305(last305 + 4); + fseek(fp, 0L, SEEK_SET); free(curbuf); free(last305); } @@ -1162,7 +1179,7 @@ void prep_mp(void) { } } -void init_post(void) { +void init_post(FILE *rfp2) { init_tau(rough); alloc_taum(k); if (randseed != 1) { @@ -1173,20 +1190,9 @@ void init_post(void) { clear_randstate(); init_randstate(randseed); } - if (rpath) { - printf("path %s\n", rpath); - if (!skip_recover) { - FILE *fp = fopen(rpath, "r"); - if (fp) { - recover(fp); - fclose(fp); - } - } - - rfp = fopen(rpath, "a"); - if (rfp == NULL) - fail("%s: %s", rpath, strerror(errno)); - setlinebuf(rfp); + if (rfp2) { + recover(rfp2); + setlinebuf(rfp2); } if (init_pattern) parse_305(init_pattern); @@ -3550,6 +3556,17 @@ void recurse(e_is jump_continue) { } } +void readme_help(void) { + +#include "read-line-coded.txt" + printf("\a\a\a"); + printf("\non Windows use like:\n"); + printf("start pcoul.exe -rresults119.txt -x9887353188984012120346 -f11 -g3 -b119 12 11\n"); + printf("pcoul.exe -x9000000000 -a 12 11\n"); + printf("For help run: pcoul.exe\n"); + printf("Print help to file run: pcoul.exe > pcoul.txt\n\n"); +} + int main(int argc, char **argv, char **envp) { int i = 1; #ifdef HAVE_SETPROCTITLE @@ -3651,16 +3668,38 @@ int main(int argc, char **argv, char **envp) { skip_recover = 1; if (i + 2 == argc) { n = strtoul(argv[i++], NULL, 10); + if (n == '\0') { + printf("\a\a\a"); + fail("\n" ANSI_COLOR_RED "Error:" ANSI_COLOR_RESET ANSI_COLOR_YELLOW "D(n,k) 'n' - Must be digit! Break." ANSI_COLOR_RESET "\n"); + } k = strtoul(argv[i++], NULL, 10); - } else - fail("wrong number of arguments"); + if (k == '\0') { + printf("\a\a\a"); + fail("\n" ANSI_COLOR_RED "Error:" ANSI_COLOR_RESET ANSI_COLOR_YELLOW "D(n,k) 'k' - Must be digit! Break." ANSI_COLOR_RESET "\n"); + } + } else { + readme_help(); + printf("\a\a\a"); + fail("\n" ANSI_COLOR_RED "Error:" ANSI_COLOR_RESET ANSI_COLOR_YELLOW " wrong number of arguments" ANSI_COLOR_RESET); + } if (force_all > k) fail("require force_all <= k"); - init_post(); + if (rpath) { + printf("path %s\n", rpath); + rfp = fopen(rpath, "a+"); + if (rfp == NULL) + fail("%s: %s", rpath, strerror(errno)); + setvbuf(rfp, NULL, 0, _IOLBF); + } + init_post(rfp); report_init(stdout, argv[0]); - if (rfp) report_init(rfp, argv[0]); - + if (rfp) { + report_init(rfp, argv[0]); + if (freopen(rpath, "a+", rfp) == NULL) + fail("could not reopen %s: %s", rpath, strerror(errno)); + setvbuf(rfp, NULL, 0, _IOLBF); + } bool jump = IS_DEEPER; if (rstack) { jump = insert_stack(); diff --git a/read-line-coded.txt b/read-line-coded.txt new file mode 100644 index 0000000..14afc4f --- /dev/null +++ b/read-line-coded.txt @@ -0,0 +1,140 @@ +printf("RUN\n"); +printf("===\n"); +printf("\n"); +printf("The Makefile will typically build a binary called 'pcoul'. The standard\n"); +printf("way to run it is:\n"); +printf(" pcoul [-r] [-f] -x\n"); +printf(" [-g] [-s] [-o] [-d]\n"); +printf(" [-j] \n"); +printf("\n"); +printf("On a Unix-like system you will usually invoke it as \"./pcoul\". On Windows\n"); +printf("you will usually invoke it as \"pcoul\" or as \"pcoul.exe\".\n"); +printf("\n"); +printf("Options:\n"); +printf("If \"-r/path/to/logfile\" is specified, progress is regularly written to the\n"); +printf("specified file (by default at least once every 600s, see 'LOG' in coul.c).\n"); +printf("If the file already exists, it will attempt to determine the last point\n"); +printf("reached according to that log, and continue processing from that point.\n"); +printf("By default there is no logfile, and progress will only be shown on the\n"); +printf("terminal.\n"); +printf("\n"); +printf("If \"-R\" is specified, the file is _not_ read to determine the point to\n"); +printf("recover from: calculation always goes from the beginning. This can be\n"); +printf("useful to combine several separate runs into a single log file.\n"); +printf("\n"); +printf("If \"-f7\" is specified, it will set force_all = 7 to treat all primes p <= 7\n"); +printf("as fully forced primes (see 'HOW IT WORKS' below). By default, force_all is\n"); +printf("set to k (the maximum) when n == 2 (mod 4), and to 0 otherwise.\n"); +printf("\n"); +printf("If \"-F7\" is specified, it will set unforce_all = 7 to treat all primes\n"); +printf("p >= 7 as unforceable. Unforceable primes are treated like partially\n"); +printf("forced primes by suppressing batches where each power of the relevant\n"); +printf("prime is one less than a power of 2. \"-F\" is equivalent to \"-F1\", to\n"); +printf("treat all primes as unforceable. Default is 0, in which case no primes\n"); +printf("are unforceable.\n"); +printf("\n"); +printf("If \"-x100:1000\" is specified, it will look for solutions v_0 with\n"); +printf("100 < v_0 <= 1000. \"-x:1000\" or \"-x1000\" are equivalent to \"-x0:1000\".\n"); +printf("Also supports exponential notation (without decimal), so \"-x13e6\"\n"); +printf("is equivalent to \"-x13000000\".\n"); +printf("The default minimum is zero; there is no default maximum: this is a\n"); +printf("required option.\n"); +printf("\n"); +printf("If \"-X\" is specified, it will search for all solutions up to the\n"); +printf("specified maximum. By default, it will search only for solutions that\n"); +printf("improve on the best found so far.\n"); +printf("Even with -X, it will still track the best solution found to report it\n"); +printf("at the end of the run.\n"); +printf("\n"); +printf("If \"-g2:3\" is specified, it will set gain = 3/2. This is a multiplier\n"); +printf("used to control the transition from recurse() to walk_v() (see 'HOW IT\n"); +printf("WORKS' below). A higher gain means it spends more time in recurse(),\n"); +printf("a lower gain means it spends more time in walk_v(). Also supports\n"); +printf("exponential notation (without decimal), so \"-g13e6\" is equivalent to\n"); +printf("\"-g13000000\". Fine-tuning the gain can make a big difference to runtime;\n"); +printf("default gain is 1.\n"); +printf("\n"); +printf("If \"-p50:100\" is specified, it will allocate (see 'HOW IT WORKS' below)\n"); +printf("only powers of primes p < 100, and will allocate at least one power of\n"); +printf("a prime p > 50. This can be used to search more selectively to improve\n"); +printf("an upper limit. \"-p:100\" or \"-p100\" are equivalent to \"-p0:100\".\n"); +printf("By default it considers all possible allocations.\n"); +printf("\n"); +printf("If \"-W100\" is specified, it will use a different process to test all\n"); +printf("possible cases involving p^e with p > 100, and then continue with the\n"); +printf("normal process as if \"-p100\" had been specified. This can give a very\n"); +printf("substantial speed improvement if the -W value is chosen with care.\n"); +printf("Default is not to do this (equivalent to -Winfinity).\n"); +printf("\n"); +printf("\"-p\" and \"-W\" may also be specified in the form \"100^2\" rather than\n"); +printf("as a simple integer, in which case it expresses a limit on the\n"); +printf("allocated power p^e rather than a limit on the prime regardless of\n"); +printf("power.\n"); +printf("\n"); +printf("The extended forms \"-px\" and \"-Wx\" can be used for fine-grained control:\n"); +printf("the minimum, maximum and threshold values in this case should be a\n"); +printf("comma-separated list of \"p^e\" override values. Thus \"-p100 -px1^5,0^11\"\n"); +printf("allows p <= 100 for all powers except that no powers of the form p^5\n"); +printf("are allowed, and all powers of the form p^11.\n"); +printf("\n"); +printf("If \"-s2\" is specified, it will initialize the random number generator\n"); +printf("with seed 2, used at least for ECM factorization. The default seed is 1,\n"); +printf("intended to help make results more reproducible.\n"); +printf("\n"); +printf("If \"-o\" is specified, it will not attempt to factorize numbers beyond\n"); +printf("a certain point, but will instead print them as a possible candidate.\n"); +printf("(**Not yet implemented.**) The default is to fully factorize numbers\n"); +printf("as far as needed to prove whether they are or are not a candidate.\n"); +printf("\n"); +printf("If \"-a\" is specified, it will establish only each valid set of batch\n"); +printf("allocations of forced primes, and output those sets assigning an index\n"); +printf("to each one (for use by '-b' below).\n"); +printf("\n"); +printf("If \"-b100\" is specified, it will find the set of batch allocations of\n"); +printf("forced primes with index 100, and run the normal calculations only\n"); +printf("over that batch.\n"); +printf("\n"); +printf("If \"-j1\" is specified, it will use \"strategy 1\" when determining the\n"); +printf("next position to which to allocate another prime power (default\n"); +printf("\"strategy 0\"). For D(120,2) with pattern \"2^7 3^4\", for example,\n"); +printf("strategy 0 will pick the second position and start allocating p^2,\n"); +printf("since it has the highest remaining tau to fulfill; strategy 1 will\n"); +printf("pick the first position and start allocating p^4, since it has the\n"); +printf("highest prime dividing the remaining tau to fulfill. \"-j2\" uses\n"); +printf("\"strategy 2\", which is the opposite of \"strategy 0\": it looks for\n"); +printf("the _lowest_ remaining tau to fill. \"-j3\" uses \"strategy 3\", which\n"); +printf("is identical to \"strategy 0\" except that if the last allocation at\n"); +printf("some position was a) unforced, and b) the square root of the remaining\n"); +printf("(even) tau, that position will automatically be picked.\n"); +printf("\"-j1\" is the default when n is divisible by at least two distinct odd\n"); +printf("primes; \"-j0\" is the default in all other cases.\n"); +printf("\n"); +printf("If \"-I...\" is specified, the argument should be a pattern of the same\n"); +printf("form as that generated for progress lines. All prime powers specified\n"); +printf("are then forced into place.\n"); +printf("\n"); +printf("If \"-m9=5\" is specified, the first element of the sequence v_0 is\n"); +printf("forced to satisfy v_0 == 5 (mod 9). This option may be specified\n"); +printf("multiple times. Note that this means only that allocations will be\n"); +printf("rejected if they are not consistent with the modular constraints:\n"); +printf("we do not preemptively work out what allocations would be required\n"); +printf("for consistency.\n"); +printf("\n"); +printf("Specifying \"-d\" enables debugging. By default, progress is shown on the\n"); +printf("terminal every 1 seconds (see \"DIAG\" in coul.c), overwriting the previous\n"); +printf("progress line each time. With \"-d\", it instead shows progress at every\n"); +printf("step on a new line (but only a single line for walk_v()). If \"-d\" is\n"); +printf("specified twice, a line is shown for each iteration of walk_v().\n"); +printf("\n"); +printf(" and are mandatory arguments, specifying that we want to search\n"); +printf("for D(n, k) (equivalently T(n/2, k) in the terminology of A292580).\n"); +printf(" must be a positive even integer; must be a positive integer.\n"); +printf("Note that this code is optimized for relatively small values of ,\n"); +printf("targetting 2 <= n <= 100; much higher n may require a lot of memory\n"); +printf("and long start-up times.\n"); +printf("\n"); +printf("\n"); +printf("HOW IT WORKS\n"); +printf("============\n"); +printf("\n"); +printf("See the wiki page .\n"); diff --git a/read-line-generate.bat b/read-line-generate.bat new file mode 100644 index 0000000..d4ab721 --- /dev/null +++ b/read-line-generate.bat @@ -0,0 +1,3 @@ +rem c:\bin\cat -v read-line.txt | c:\bin\sed "s/^/""/" | c:\bin\sed "s/$/""/" +rem c:\bin\cat -v read-line.txt | c:\bin\sed "s/"""/\\\\"""/g" +c:\bin\cat -v read-line.txt | c:\bin\sed "s/"""/\\\\"""/g"| c:\bin\sed "s/^/printf(""/" | c:\bin\sed "s/$/\\\n/" | c:\bin\sed "s/$/"");/" > read-line-coded.txt diff --git a/read-line-generate.sh b/read-line-generate.sh new file mode 100644 index 0000000..ae6cd12 --- /dev/null +++ b/read-line-generate.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cat -v read-line.txt | sed 's/"/\\"/g'| sed 's/^/printf("/' | sed 's/$/\\n/' | sed 's/$/");/' > read-line-coded.txt + +#EOF \ No newline at end of file diff --git a/read-line.txt b/read-line.txt new file mode 100644 index 0000000..66d827c --- /dev/null +++ b/read-line.txt @@ -0,0 +1,140 @@ +RUN +=== + +The Makefile will typically build a binary called 'pcoul'. The standard +way to run it is: + pcoul [-r] [-f] -x + [-g] [-s] [-o] [-d] + [-j] + +On a Unix-like system you will usually invoke it as "./pcoul". On Windows +you will usually invoke it as "pcoul" or as "pcoul.exe". + +Options: +If "-r/path/to/logfile" is specified, progress is regularly written to the +specified file (by default at least once every 600s, see 'LOG' in coul.c). +If the file already exists, it will attempt to determine the last point +reached according to that log, and continue processing from that point. +By default there is no logfile, and progress will only be shown on the +terminal. + +If "-R" is specified, the file is _not_ read to determine the point to +recover from: calculation always goes from the beginning. This can be +useful to combine several separate runs into a single log file. + +If "-f7" is specified, it will set force_all = 7 to treat all primes p <= 7 +as fully forced primes (see 'HOW IT WORKS' below). By default, force_all is +set to k (the maximum) when n == 2 (mod 4), and to 0 otherwise. + +If "-F7" is specified, it will set unforce_all = 7 to treat all primes +p >= 7 as unforceable. Unforceable primes are treated like partially +forced primes by suppressing batches where each power of the relevant +prime is one less than a power of 2. "-F" is equivalent to "-F1", to +treat all primes as unforceable. Default is 0, in which case no primes +are unforceable. + +If "-x100:1000" is specified, it will look for solutions v_0 with +100 < v_0 <= 1000. "-x:1000" or "-x1000" are equivalent to "-x0:1000". +Also supports exponential notation (without decimal), so "-x13e6" +is equivalent to "-x13000000". +The default minimum is zero; there is no default maximum: this is a +required option. + +If "-X" is specified, it will search for all solutions up to the +specified maximum. By default, it will search only for solutions that +improve on the best found so far. +Even with -X, it will still track the best solution found to report it +at the end of the run. + +If "-g2:3" is specified, it will set gain = 3/2. This is a multiplier +used to control the transition from recurse() to walk_v() (see 'HOW IT +WORKS' below). A higher gain means it spends more time in recurse(), +a lower gain means it spends more time in walk_v(). Also supports +exponential notation (without decimal), so "-g13e6" is equivalent to +"-g13000000". Fine-tuning the gain can make a big difference to runtime; +default gain is 1. + +If "-p50:100" is specified, it will allocate (see 'HOW IT WORKS' below) +only powers of primes p < 100, and will allocate at least one power of +a prime p > 50. This can be used to search more selectively to improve +an upper limit. "-p:100" or "-p100" are equivalent to "-p0:100". +By default it considers all possible allocations. + +If "-W100" is specified, it will use a different process to test all +possible cases involving p^e with p > 100, and then continue with the +normal process as if "-p100" had been specified. This can give a very +substantial speed improvement if the -W value is chosen with care. +Default is not to do this (equivalent to -Winfinity). + +"-p" and "-W" may also be specified in the form "100^2" rather than +as a simple integer, in which case it expresses a limit on the +allocated power p^e rather than a limit on the prime regardless of +power. + +The extended forms "-px" and "-Wx" can be used for fine-grained control: +the minimum, maximum and threshold values in this case should be a +comma-separated list of "p^e" override values. Thus "-p100 -px1^5,0^11" +allows p <= 100 for all powers except that no powers of the form p^5 +are allowed, and all powers of the form p^11. + +If "-s2" is specified, it will initialize the random number generator +with seed 2, used at least for ECM factorization. The default seed is 1, +intended to help make results more reproducible. + +If "-o" is specified, it will not attempt to factorize numbers beyond +a certain point, but will instead print them as a possible candidate. +(**Not yet implemented.**) The default is to fully factorize numbers +as far as needed to prove whether they are or are not a candidate. + +If "-a" is specified, it will establish only each valid set of batch +allocations of forced primes, and output those sets assigning an index +to each one (for use by '-b' below). + +If "-b100" is specified, it will find the set of batch allocations of +forced primes with index 100, and run the normal calculations only +over that batch. + +If "-j1" is specified, it will use "strategy 1" when determining the +next position to which to allocate another prime power (default +"strategy 0"). For D(120,2) with pattern "2^7 3^4", for example, +strategy 0 will pick the second position and start allocating p^2, +since it has the highest remaining tau to fulfill; strategy 1 will +pick the first position and start allocating p^4, since it has the +highest prime dividing the remaining tau to fulfill. "-j2" uses +"strategy 2", which is the opposite of "strategy 0": it looks for +the _lowest_ remaining tau to fill. "-j3" uses "strategy 3", which +is identical to "strategy 0" except that if the last allocation at +some position was a) unforced, and b) the square root of the remaining +(even) tau, that position will automatically be picked. +"-j1" is the default when n is divisible by at least two distinct odd +primes; "-j0" is the default in all other cases. + +If "-I..." is specified, the argument should be a pattern of the same +form as that generated for progress lines. All prime powers specified +are then forced into place. + +If "-m9=5" is specified, the first element of the sequence v_0 is +forced to satisfy v_0 == 5 (mod 9). This option may be specified +multiple times. Note that this means only that allocations will be +rejected if they are not consistent with the modular constraints: +we do not preemptively work out what allocations would be required +for consistency. + +Specifying "-d" enables debugging. By default, progress is shown on the +terminal every 1 seconds (see "DIAG" in coul.c), overwriting the previous +progress line each time. With "-d", it instead shows progress at every +step on a new line (but only a single line for walk_v()). If "-d" is +specified twice, a line is shown for each iteration of walk_v(). + + and are mandatory arguments, specifying that we want to search +for D(n, k) (equivalently T(n/2, k) in the terminology of A292580). + must be a positive even integer; must be a positive integer. +Note that this code is optimized for relatively small values of , +targetting 2 <= n <= 100; much higher n may require a lot of memory +and long start-up times. + + +HOW IT WORKS +============ + +See the wiki page .