mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
158 lines
3.7 KiB
Plaintext
158 lines
3.7 KiB
Plaintext
/*
|
|
* Copyright (c) 1996 Landon Curt Noll
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and
|
|
* its documentation for any purpose and without fee is hereby granted,
|
|
* provided that the above copyright, this permission notice and text
|
|
* this comment, and the disclaimer below appear in all of the following:
|
|
*
|
|
* supporting documentation
|
|
* source copies
|
|
* source works derived from this source
|
|
* binaries derived from this source or from derived source
|
|
*
|
|
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
|
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
|
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* chongo was here /\../\ chongo@toad.com
|
|
*/
|
|
|
|
|
|
/*
|
|
* mfactor - find a factor of a Mersenne Number
|
|
*
|
|
* Mersenne numbers are numbers of the form:
|
|
*
|
|
* 2^n-1 for integer n > 0
|
|
*
|
|
* We know that factors of a Mersenne number are of the form:
|
|
*
|
|
* 2*k*n+1 and +/- 1 mod 8
|
|
*
|
|
* given:
|
|
* n attempt to factor M(n) = 2^n-1
|
|
* start_k the value k in 2*k*n+1 to start the search
|
|
* rept_loop loop cycle reporting, 0 => none
|
|
*
|
|
* returns:
|
|
* factor of M(n)
|
|
*/
|
|
define mfactor(n, start_k, rept_loop)
|
|
{
|
|
local q; /* test factor 2*k*n+1 */
|
|
local k; /* k in 2*k*n+1 */
|
|
local step2; /* 2*n */
|
|
local step6; /* 6*n */
|
|
local mod8; /* q mod 8 */
|
|
local loop; /* report loop count */
|
|
|
|
/*
|
|
* firewall
|
|
*/
|
|
if (!isint(n) || n <= 0) {
|
|
quit "n must be an integer > 0";
|
|
}
|
|
if (isnull(start_k)) {
|
|
start_k = 1;
|
|
} else if (!isint(start_k) || start_k <= 0) {
|
|
quit "start_k must be an integer > 0";
|
|
}
|
|
if (!isint(rept_loop)) {
|
|
rept_loop = 0;
|
|
}
|
|
|
|
/*
|
|
* setup
|
|
*/
|
|
step2 = 2*n;
|
|
step6 = 6*n;
|
|
k = start_k - 1;
|
|
q = 2*k*n+1;
|
|
/* step2 to the first factor candidate */
|
|
do {
|
|
q += step2;
|
|
mod8 = mod(q,8);
|
|
++k;
|
|
} while (mod8 != 1 && mod8 != 7);
|
|
|
|
/*
|
|
* At this point we are at either at the first or second
|
|
* of two consequtive factor candidates depending on if
|
|
* the next to k values are 1 and 7 mod 8.
|
|
*
|
|
* The loops below assume that we will test, bump k by 1
|
|
* (move to the 2nd consequtive factor candidate), test and
|
|
* bump k by 3 (move to the first of the next consequtive
|
|
* factor candidate pair).
|
|
*
|
|
* In order to prepair, we need to move to the first of
|
|
* a consequtive factor candidate pair. If we happen to
|
|
* be on a the 2nd of a pair, we will test it outside
|
|
* of the loop and bump to the first of the next pair.
|
|
*/
|
|
mod8 = mod(q+step2,8);
|
|
if (mod8 != 1 && mod8 != 7) {
|
|
/*
|
|
* q is the 2nd of a consequtive factor candidate pair
|
|
* so we test q now and bump k by 3.
|
|
*/
|
|
if (pmod(2,n,q) == 1) {
|
|
/* q was a factor afterall, no need to do more! */
|
|
return q;
|
|
}
|
|
q += step6;
|
|
k += 3;
|
|
}
|
|
|
|
/*
|
|
* look for a factor
|
|
*/
|
|
loop = k;
|
|
while (pmod(2,n,q) != 1) {
|
|
|
|
/*
|
|
* determine if we need to report
|
|
*/
|
|
if (rept_loop > 0) {
|
|
if (rept_loop <= ++loop) {
|
|
/* report this loop */
|
|
printf("at 2*%d*%d+1, cpu: %f\n",
|
|
k, n, runtime());
|
|
fflush(files(1));
|
|
loop = 0;
|
|
}
|
|
k += 4;
|
|
}
|
|
|
|
/*
|
|
* 1st of a consequtive factor candidate pair is not
|
|
* a factor, try the 2nd of that pair
|
|
*/
|
|
q += step2;
|
|
if (pmod(2,n,q) == 1) {
|
|
break; /* factor found */
|
|
}
|
|
|
|
/*
|
|
* 2nd of a consequtive factor candidate pair is not
|
|
* a factor, try the next pair
|
|
*/
|
|
q += step6;
|
|
}
|
|
|
|
/*
|
|
* return the factor found
|
|
*/
|
|
return q;
|
|
}
|
|
|
|
global lib_debug;
|
|
if (lib_debug >= 0) {
|
|
print "mfactor(n [, start_k [, rept_loop]])"
|
|
}
|