diff --git a/CHANGES b/CHANGES index 079723b..669e737 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,19 @@ The following are the changes from calc version 2.12.6.1 to date: Fixed an C code indenting issue that was reported by Thomas Walter in zfunc.c. + Fixed a man page warning about ./myfile where the leading dot + was mistook for an nroff macro. Thanks goes to David Haller + for providing the patch. + + Improved gen_v1(h,n) in lucas.cal for cases where h is not a + multiple of 3. Optimized the search for v(1) when h is a + multiple of 3. + + Fixed a Makefile problem, reported by Doug Hays , where if a macOS user set BINDIR, LIBDIR, CALC_SHAREDIR + or INCDIR in the top section, their values will be overwritten by + the Darwin specific section. + The following are the changes from calc version 2.12.6.0 to 2.12.6.0: diff --git a/Makefile.ship b/Makefile.ship index 782fdf0..633a8c0 100644 --- a/Makefile.ship +++ b/Makefile.ship @@ -23,7 +23,7 @@ # READLINE_LIB= -lreadline # READLINE_EXTRAS= -lhistory -lncurses # -# Copyright (C) 1999-2017 Landon Curt Noll +# Copyright (C) 1999-2018 Landon Curt Noll # # Calc is open software; you can redistribute it and/or modify it under # the terms of version 2.1 of the GNU Lesser General Public License @@ -564,14 +564,30 @@ HAVE_UNUSED= # # INCDIR= /dev/env/DJDIR/include # -# If in doubt, set: +# If in doubt, for non-macOS hosts set: # # INCDIR= /usr/include # +# However, if you are on macOS then set: +# +# INCDIR= /usr/local/include +#if 0 /* start of skip for non-Gnu makefiles */ +ifeq ($(target),Darwin) +# default INCDIR for macOS +INCDIR= /usr/local/include + +else +#endif /* end of skip for non-Gnu makefiles */ + +# default INCDIR for non-macOS +INCDIR= /usr/include #INCDIR= /usr/local/include #INCDIR= /dev/env/DJDIR/include -INCDIR= /usr/include + +#if 0 /* start of skip for non-Gnu makefiles */ +endif +#endif /* end of skip for non-Gnu makefiles */ # Where to install calc related things # @@ -602,23 +618,71 @@ INCDIR= /usr/include # LIBDIR= /dev/env/DJDIR/lib # CALC_SHAREDIR= /dev/env/DJDIR/share/calc # -# If in doubt, set: +# If in doubt, for non-macOS hosts set: # # BINDIR= /usr/bin # LIBDIR= /usr/lib # CALC_SHAREDIR= /usr/share/calc # +# However, if you are on macOS then set: +# +# BINDIR= /usr/local/bin +# LIBDIR= /usr/local/lib +# CALC_SHAREDIR= /usr/local/share/calc +# +# NOTE: Starting with macOS El Capitan OS X 10.11, root by default +# could not mkdir under system locations, so macOS must now +# use the /usr/local tree. + +#if 0 /* start of skip for non-Gnu makefiles */ +ifeq ($(target),Darwin) + +# default BINDIR for macOS +BINDIR= /usr/local/bin + +else +#endif /* end of skip for non-Gnu makefiles */ + +# default BINDIR for non-macOS +BINDIR= /usr/bin #BINDIR= /usr/local/bin #BINDIR= /dev/env/DJDIR/bin -BINDIR= /usr/bin +#if 0 /* start of skip for non-Gnu makefiles */ +endif + +ifeq ($(target),Darwin) + +# default LIBDIR for macOS +LIBDIR= /usr/local/lib + +else +#endif /* end of skip for non-Gnu makefiles */ + +# default LIBDIR for non-macOS +LIBDIR= /usr/lib #LIBDIR= /usr/local/lib #LIBDIR= /dev/env/DJDIR/lib -LIBDIR= /usr/lib +#if 0 /* start of skip for non-Gnu makefiles */ +endif + +ifeq ($(target),Darwin) + +# default CALC_SHAREDIR for macOS +CALC_SHAREDIR= /usr/local/share/calc + +else +#endif /* end of skip for non-Gnu makefiles */ + +# default CALC_SHAREDIR for non-macOS +CALC_SHAREDIR= /usr/share/calc #CALC_SHAREDIR= /usr/local/lib/calc #CALC_SHAREDIR= /dev/env/DJDIR/share/calc -CALC_SHAREDIR= /usr/share/calc + +#if 0 /* start of skip for non-Gnu makefiles */ +endif +#endif /* end of skip for non-Gnu makefiles */ # NOTE: Do not set CALC_INCDIR to /usr/include or /usr/local/include!!! # Always be sure that the CALC_INCDIR path ends in /calc to avoid @@ -990,7 +1054,7 @@ EXT= # The default calc versions # -VERSION= 2.12.6.3 +VERSION= 2.12.6.4 # Names of shared libraries with versions # @@ -1263,16 +1327,6 @@ LDCONFIG:= # DARWIN_ARCH= -arch ppc # PPC binary # DARWIN_ARCH= -arch x86_64 # native 64-bit binary DARWIN_ARCH= # native binary -# -# Starting with El Capitan OS X 10.11, root by default could not -# mkdir under system locations, so we now use the /usr/local tree. -# -OPTDIR:= /usr/local -BINDIR:= /${OPTDIR}/bin -LIBDIR:= /${OPTDIR}/lib -CALC_SHAREDIR:= /${OPTDIR}/share -CALC_INCDIR:= /${OPTDIR}/include -SCRIPTDIR:= ${BINDIR}/cscript endif ################## diff --git a/cal/lucas.cal b/cal/lucas.cal index a7c2055..56a8378 100644 --- a/cal/lucas.cal +++ b/cal/lucas.cal @@ -28,6 +28,10 @@ * For a general tutorial on how to find a new largest known prime, see: * * http://www.isthe.com/chongo/tech/math/prime/prime-tutorial.pdf + * + * Also see the reference code, available both C and go: + * + * https://github.com/arcetri/goprime */ /* @@ -154,6 +158,12 @@ * * Finally, one should eliminate all values of 'h*2^n-1' where * 'h*2^n+1' is divisible by a small primes. + * + * NOTE: Today, for world record sized h*2^n-1 primes, one might + * search for factors < 2^46 or more. By excluding h*2^n-1 + * with prime factors < 2^46, where h*2^n-1 is a bit larger + * than the largest known prime, one may exclude about 96.5% + * of candidates that have "small" prime factors. */ pprod256 = 0; /* product of "primes up to 256" / "primes up to 46" */ @@ -805,84 +815,154 @@ rodseth_xhn(x, h, n) * * The above distribution was found to hold fairly well over many values of * odd h that are also a multiple of 3 and for many values of n where h < 2^n. + * * For example for in a sample size of 1000000 numbers of the form h*2^n-1 * where h is an odd multiple of 3, 12996351 <= h <= 13002351, * 4331116 <= n <= 4332116, these are the smallest v(1) values that were found: * - * smallest percentage - * v(1) used - * ------------------- - * 3 40.0000% - * 5 25.6833% - * 9 11.6924% - * 11 10.4528% - * 15 4.8048% - * 17 2.3458% - * 21 1.6568% - * 29 1.2814% - * 27 0.6906% - * 35 0.4529% - * 39 0.3140% - * 41 0.1737% - * 31 0.1413% - * 45 0.1173% - * 51 0.0526% - * 55 0.0350% - * 49 0.0332% - * 59 0.0218% - * 69 0.0099% - * 65 0.0085% - * 71 0.0073% - * 57 0.0062% - * 85 0.0048% - * 81 0.0044% - * 95 0.0028% - * 99 0.0017% - * 77 0.0009% - * 53 0.0008% - * 67 0.0004% - * 105 0.0004% - * 111 0.0004% - * 125 0.0004% - * 87 0.0003% - * 101 0.0002% - * 83 0.0001% - * 109 0.0001% - * 121 0.0001% - * 129 0.0001% + * smallest percentage + * v(1) used + * -------- --------- + * 3 40.0000 % + * 5 25.6833 % + * 9 11.6924 % + * 11 10.4528 % + * 15 4.8048 % + * 17 2.3458 % + * 21 1.3734 % + * 29 1.0527 % + * 20 0.8595 % + * 27 0.5758 % + * 35 0.4420 % + * 36 0.2433 % + * 39 0.1779 % + * 41 0.0885 % + * 45 0.0571 % + * 32 0.0337 % + * 51 0.0289 % + * 44 0.0205 % + * 49 0.0176 % + * 56 0.0137 % + * 59 0.0108 % + * 57 0.0053 % + * 65 0.0047 % + * 55 0.0045 % + * 69 0.0031 % + * 71 0.0024 % + * 66 0.0011 % + * 95 0.0008 % + * 81 0.0008 % + * 77 0.0006 % + * 72 0.0005 % + * 99 0.0004 % + * 80 0.0003 % + * 74 0.0003 % + * 84 0.0002 % + * 67 0.0002 % + * 87 0.0001 % + * 104 0.0001 % + * 129 0.0001 % * + * However, a case can be made for considering only odd values for v(1) candidates. * When h * 2^n-1 is prime and h is an odd multiple of 3, a smallest v(1) that - * is even is extremely rate. Of the list of 127287 known primes of the form - * h*2^n-1 when h was a multiple of 3, none has an smallest v(1) that was even. + * is even is extremely rate. Of the list of 146553 known primes of the form + * h*2^n-1 when h is an odd a multiple of 3, none has an smallest v(1) that was even. * - * About 1 out of 1000000 cases when h is a multiple of 3 use v(1) > 127 as the - * smallest value of v(1). + * See: + * + * https://github.com/arcetri/verified-prime + * + * for that list of 146553 known primes of the form h*2^n-1. + * + * That same example for in a sample size of 1000000 numbers of the form h*2^n-1 + * where h is an odd multiple of 3, 12996351 <= h <= 13002351, + * 4331116 <= n <= 4332116, these are the smallest odd v(1) values that were found: + * + * smallest percentage + * odd v(1) used + * -------- --------- + * 3 40.0000 % + * 5 25.6833 % + * 9 11.6924 % + * 11 10.4528 % + * 15 4.8048 % + * 17 2.3458 % + * 21 1.6568 % + * 29 1.6174 % + * 35 0.4529 % + * 27 0.3546 % + * 39 0.3470 % + * 41 0.2159 % + * 45 0.1173 % + * 31 0.0661 % + * 51 0.0619 % + * 55 0.0419 % + * 59 0.0250 % + * 49 0.0170 % + * 69 0.0110 % + * 65 0.0098 % + * 71 0.0078 % + * 85 0.0048 % + * 81 0.0044 % + * 95 0.0038 % + * 99 0.0021 % + * 125 0.0009 % + * 57 0.0007 % + * 111 0.0005 % + * 77 0.0003 % + * 165 0.0003 % + * 155 0.0002 % + * 129 0.0002 % + * 101 0.0002 % + * 53 0.0001 % + * + * Moreover when evaluating odd candidates for v(1), one may cache Jacobi symbol + * evaluations to reduce the number of Jacobi symbol evaluations to a minimum. + * For example, if one tests 5 and finds that the 2nd case fails: + * + * jacobi(5+2, h*2^n-1) != -1 + * + * Then if one is later testing 9, the Jacobi symbol value for the first 1st case: + * + * jacobi(7-2, h*2^n-1) + * + * is already known. + * + * The hit rate in the cache improves (thus fewer Jacobi symbols need evaluating) + * if we sort the above "smallest odd v(1) values" in numerical order. + * Without Jacobi symbol value caching, it requires on average + * 4.851377 Jacobi symbol evaluations. With Jacobi symbol value caching + * cacheing, an averare of 4.348820 Jacobi symbol evaluations is needed. * * Given this information, when odd h is a multiple of 3 we try, in order, - * these sorted values of X: + * these sorted odd values of X: * - * 3, 5, 9, 11, 15, 17, 21, 27, 29, 31, 35, 39, 41, 45, 49, 51, 53, 55, 57, 59, - * 65, 67, 69, 71, 77, 81, 83, 85, 87, 95, 99, 101, 105, 109, 111, 121, 125 + * 3, 5, 9, 11, 15, 17, 21, 29, 27, 35, 39, 41, 31, 45, 51, 55, 49, 59, + * 69, 65, 71, 57, 85, 81, 95, 99, 77, 53, 67, 125, 111, 105, 87, 129, + * 101, 83, 165, 155, 149, 141, 121, 109 * * And stop on the first value of X where: * * jacobi(X-2, h*2^n-1) == 1 * jacobi(X+2, h*2^n-1) == -1 * - * If no value in that list works, we start simple search starting with X = 129 + * Less than 1 case out of 1000000 will not be satisifed by the above sorted list. + * If no value in that list works, we start simple search starting with X = 167 * and incrementing by 2 until a value of X is found. * - * The x_tbl[] matrix contains those common values of X to try in order. - * If all x_tbl_len fail to satisfy Ref4 condition 1, then we begin a - * linear search at next_x until we find a proper X value. + * The x_tbl[] matrix contains those values of X to try in order. + * If all x_tbl_len fail to satisfy Ref4 condition 1 (this happens less than + * 1 in 1000000 cases), then we begin a linear search of odd values starting at + * next_x until we find a proper X value. */ -x_tbl_len = 38; +x_tbl_len = 42; mat x_tbl[x_tbl_len]; x_tbl = { - 3, 5, 9, 11, 15, 17, 21, 27, 29, 31, 35, 39, 41, 45, 49, 51, 53, 55, 57, 59, - 65, 67, 69, 71, 77, 81, 83, 85, 87, 95, 99, 101, 105, 109, 111, 121, 125 + 3, 5, 9, 11, 15, 17, 21, 29, 27, 35, 39, 41, 31, 45, 51, 55, 49, 59, + 69, 65, 71, 57, 85, 81, 95, 99, 77, 53, 67, 125, 111, 105, 87, 129, + 101, 83, 165, 155, 149, 141, 121, 109 }; -next_x = 129; +next_x = 167; /* must be 2 more than the largest value in x_tbl[] */ /* * gen_v1 - compute the v(1) for a given h*2^n-1 if we can @@ -940,12 +1020,22 @@ next_x = 129; * * u(2) = v(h) (NOTE: some call this u(2)) * - * so we simply return + * so we can always return * * v(1) = alpha^1 + alpha^(-1) * = (2+sqrt(3)) + (2-sqrt(3)) * = 4 * + * In 40% of the cases when h is not a multiple of 3, 3 is a valid value + * for v(1). We can test if 3 is a valid value for v(1) in this case: + * + * if jacobi(1, h*2^n-1) == 1 and jacobi(5, h*2^n-1) == -1, then + * v(1) = 3 + * else + * v(1) = 4 + * + * HOTE: The above "if then else" works only of h is not a multiple of 3. + * *** * * Case 2: (h mod 3 == 0) @@ -1049,6 +1139,10 @@ gen_v1(h, n) { local x; /* potential v(1) to test */ local i; /* x_tbl index */ + local v1m2; /* X-2 1st case */ + local v1p2; /* X+2 2nd case */ + local testval; /* h*2^n-1 - value we are testing if prime */ + local mat cached_v1[next_x]; /* cached Jacobi symbol values or 0 */ /* * check arg types @@ -1081,14 +1175,24 @@ gen_v1(h, n) * check for Case 1: (h mod 3 != 0) */ if (h % 3 != 0) { - /* v(1) is easy to compute */ - return 4; + if (rodseth_xhn(3, h, n) == 1) { + /* 40% of the time, 3 works when h mod 3 != 0 */ + return 3; + } else { + /* otherwise 4 always works when h mod 3 != 0 */ + return 4; + } } /* * What follow is Case 2: (h mod 3 == 0) */ + /* + * clear cache + */ + matfill(cached_v1, 0); + /* * We will look for x that satisfies conditions in Ref4, condition 1: * @@ -1100,26 +1204,51 @@ gen_v1(h, n) * to the next odd value, the now jacobi(X-2, h*2^n-1) * does not need to be re-evaluted. */ + testval = h*2^n-1; for (i=0; i < x_tbl_len; ++i) { /* - * test Ref4 condition 1: + * obtain the next test candidate */ x = x_tbl[i]; - if (rodseth_xhn(x, h, n) == 1) { - /* - * found a x that satisfies Ref4 condition 1 - */ - ldebug("gen_v1", "h= " + str(h) + " n= " + str(n) + - " v1= " + str(x) + " using tbl[ " + - str(i) + " ]"); - return x; + /* + * Check x for condition 1 part 1 + * + * jacobi(x-2, h*2^n-1) == 1 + */ + v1m2 = x-2; + if (cached_v1[v1m2] == 0) { + cached_v1[v1m2] = jacobi(v1m2, testval); } + if (cached_v1[v1m2] != 1) { + continue; + } + + /* + * Check x for condition 1 part 2 + * + * jacobi(x+2, h*2^n-1) == -1 + */ + v1p2 = x+2; + if (cached_v1[v1p2] == 0) { + cached_v1[v1p2] = jacobi(v1p2, testval); + } + if (cached_v1[v1p2] != -1) { + continue; + } + + /* + * found a x that satisfies Ref4 condition 1 + */ + ldebug("gen_v1", "h= " + str(h) + " n= " + str(n) + + " v1= " + str(x) + " using tbl[ " + + str(i) + " ]"); + return x; } /* - * We are in that rare case (about 1 in 835 000) where none of the + * We are in that rare case (less than 1 in 1 000 000) where none of the * common X values satisfy Ref4 condition 1. We start a linear search * of odd vules at next_x from here on. */ diff --git a/custom/Makefile b/custom/Makefile index 81d094e..3064ef1 100644 --- a/custom/Makefile +++ b/custom/Makefile @@ -348,7 +348,7 @@ EXT= # The default calc versions # -VERSION= 2.12.6.3 +VERSION= 2.12.6.4 # Names of shared libraries with versions # @@ -628,16 +628,6 @@ LDCONFIG:= # DARWIN_ARCH= -arch ppc # PPC binary # DARWIN_ARCH= -arch x86_64 # native 64-bit binary DARWIN_ARCH= # native binary -# -# Starting with El Capitan OS X 10.11, root by default could not -# mkdir under system locations, so we now use the /usr/local tree. -# -OPTDIR:= /usr/local -BINDIR:= /${OPTDIR}/bin -LIBDIR:= /${OPTDIR}/lib -CALC_SHAREDIR:= /${OPTDIR}/share -CALC_INCDIR:= /${OPTDIR}/include -SCRIPTDIR:= ${BINDIR}/cscript endif ################## diff --git a/custom/Makefile.head b/custom/Makefile.head index a43a90a..3e6e783 100644 --- a/custom/Makefile.head +++ b/custom/Makefile.head @@ -348,7 +348,7 @@ EXT= # The default calc versions # -VERSION= 2.12.6.3 +VERSION= 2.12.6.4 # Names of shared libraries with versions # diff --git a/version.c b/version.c index f2e7896..4ca99c4 100644 --- a/version.c +++ b/version.c @@ -45,7 +45,7 @@ static char *program; #define MAJOR_VER 2 /* major library version */ #define MINOR_VER 12 /* minor library version */ #define MAJOR_PATCH 6 /* major software level under library version */ -#define MINOR_PATCH 3 /* minor software level or 0 if not patched */ +#define MINOR_PATCH 4 /* minor software level or 0 if not patched */ /*