Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 62 additions & 23 deletions coul.c
Original file line number Diff line number Diff line change
@@ -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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
Expand All @@ -12,7 +18,11 @@
# include <sys/types.h>
#endif
#include <signal.h>
#ifdef __CYGWIN__
/* noop */
#else
#include <time.h>
#endif
#include <sys/time.h>
#include <sys/resource.h>

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -317,6 +330,7 @@ void report(char *format, ...) {
gmp_vfprintf(rfp, format, ap);
va_end(ap);
fflush(rfp);
t0 = utime();
}
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
140 changes: 140 additions & 0 deletions read-line-coded.txt
Original file line number Diff line number Diff line change
@@ -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<path to logfile>] [-f<force primes>] -x<min:max>\n");
printf(" [-g<damp:gain] [-p<minp:maxp>] [-s<randseed>] [-o] [-d]\n");
printf(" [-j<strategy>] <n> <k>\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("<n> and <k> 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("<n> must be a positive even integer; <k> must be a positive integer.\n");
printf("Note that this code is optimized for relatively small values of <n>,\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 <https://github.com/hvds/divrep/wiki/D(n,k)-calculation>.\n");
3 changes: 3 additions & 0 deletions read-line-generate.bat
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions read-line-generate.sh
Original file line number Diff line number Diff line change
@@ -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
Loading