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 */
/*
|