⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfactor.cal

📁 Calc Software Package for Number Calc
💻 CAL
字号:
/* * mfactor - return the lowest factor of 2^n-1, for n > 0 * * Copyright (C) 1999  Landon Curt Noll * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL.  You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. * * @(#) $Revision: 29.3 $ * @(#) $Id: mfactor.cal,v 29.3 2006/12/16 11:18:46 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/cal/RCS/mfactor.cal,v $ * * Under source code control:	1996/07/06 06:09:40 * File existed as early as:	1996 * * chongo <was here> /\oo/\	http://www.isthe.com/chongo/ * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ *//* * hset method * * We will assume that mfactor is called with p_elim == 17. * *	n = (the Mersenne exponent we are testing) *	Q = 4*2*3*5*7*11*13*17 (4 * pfact(of some reasonable integer)) * * We first determine all values of h mod Q such that: * *	gcd(h*n+1, Q) == 1   and   h*n+1 == +/-1 mod 8 * * There will be 2*1*2*4*6*10*12*16 such values of h. * * For efficiency, we keep the difference between consecutive h values * in the hset[] difference array with hset[0] being the first h value. * Last, we multiply the hset[] values by n so that we only need * to add sequential values of hset[] to get factor candidates. * * We need only test factors of the form: * *	(Q*g*n + hx) + 1 * * where: * *	g is an integer >= 0 *	hx is computed from hset[] difference value described above * * Note that (Q*g*n + hx) is always even and that hx is a multiple * of n.  Thus the typical factor form: * *	2*k*n + 1 * * implies that: * *	k = (Q*g + hx/n)/2 * * This allows us to quickly eliminate factor values that are divisible * by 2, 3, 5, 7, 11, 13 or 17.	 (well <= p value found below) * * The following loop shows how test_factor is advanced to higher test * values using hset[].	 Here, hcount is the number of elements in hset[]. * It can be shown that hset[0] == 0.  We add hset[hcount] to the hset[] * array for looping control convenience. * *	(* increase test_factor thru other possible test values *) *	test_factor = 0; *	hindx = 0; *	do { *		while (++hindx <= hcount) { *			test_factor += hset[hindx]; *		} *		hindx = 0; *	} while (test_factor < some_limit); * * The test, mfactor(67, 1, 10000) took on an 200 Mhz r4k (user CPU seconds): * *	210.83	(prior to use of hset[]) *	 78.35	(hset[] for p_elim = 7) *	 73.87	(hset[] for p_elim = 11) *	 73.92	(hset[] for p_elim = 13) *	234.16	(hset[] for p_elim = 17) *	p_elim == 19 requires over 190 Megs of memory * * Over a long period of time, the call to load_hset() becomes insignificant. * If we look at the user CPU seconds from the first 10000 cycle to the * end of the test we find: * *	205.00	(prior to use of hset[]) *	 75.89	(hset[] for p_elim = 7) *	 73.74	(hset[] for p_elim = 11) *	 70.61	(hset[] for p_elim = 13) *	 57.78	(hset[] for p_elim = 17) *	 p_elim == 19 rejected because of memory size * * The p_elim == 17 overhead takes ~3 minutes on an 200 Mhz r4k CPU and * requires about ~13 Megs of memory.  The p_elim == 13 overhead * takes about 3 seconds and requires ~1.5 Megs of memory. * * The value p_elim == 17 is best for long factorizations.  It is the * fastest even thought the initial startup overhead is larger than * for p_elim == 13. * * NOTE: The values above are prior to optimizations where hset[] was *	 multiplied by n plus other optimizations.  Thus, the CPU *	 times you may get will not likely match the above values. *//* * 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 * * We make use of the hset[] difference array to eliminate factor * candidates that would otherwise be divisible by 2, 3, 5, 7 ... p_elim. * * given: *	n		attempt to factor M(n) = 2^n-1 *	start_k		the value k in 2*k*n+1 to start the search (def: 1) *	rept_loop	loop cycle reporting (def: 10000) *	p_elim		largest prime to eliminate from test factors (def: 17) * * returns: *	factor of (2^n)-1 * * NOTE: The p_elim argument is optional and defaults to 17.  A p_elim value *	 of 17 is faster than 13 for even medium length runs.  However 13 *	 uses less memory and has a shorter startup time. */define mfactor(n, start_k, rept_loop, p_elim){	local Q;	/* 4*pfact(p_elim), hset[] cycle size */	local hcount;	/* elements in the hset[] difference array */	local loop;	/* report loop count */	local q;	/* test factor of 2^n-1 */	local g;	/* g as in test candidate form: (Q*g*hset[i])*n + 1 */	local hindx;	/* hset[] index */	local i;	local tmp;	local tmp2;	/*	 * firewall	 */	if (!isint(n) || n <= 0) {		quit "n must be an integer > 0";	}	if (!isint(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 = 10000;	}	if (rept_loop < 1) {		quit "rept_loop must be an integer > 0";	}	if (!isint(p_elim)) {		p_elim = 17;	}	if (p_elim < 3) {		quit "p_elim must be an integer > 2 (try 13 or 17)";	}	/*	 * declare our global values	 */	Q = 4*pfact(p_elim);	hcount = 2;	/* allocate the h difference array */	for (i=2; i <= p_elim; i = nextcand(i)) {		hcount *= (i-1);	}	local mat hset[hcount+1];	/*	 * load the hset[] difference array	 */	{		local x;	/* h*n+1 mod 8 */		local h;	/* potential h value */		local last_h;	/* previous valid h value */		last_h = 0;		for (i=0,h=0; h < Q; ++h) {			if (gcd(h*n+1,Q) == 1) {				x = (h*n+1) % 8;				if (x == 1 || x == 7) {					hset[i++] = (h-last_h) * n;					last_h = h;				}			}		}		hset[hcount] = Q*n - last_h*n;	}	/*	 * setup	 *	 * determine the next g and hset[] index (hindx) values such that:	 *	 *	2*start_k <= (Q*g + hset[hindx])	 *	 * and (Q*g + hset[hindx]) is a minimum and where:	 *	 *	Q = (4 * pfact(of some reasonable integer))	 *	g = (some integer) (hset[] cycle number)	 *	 * We also compute 'q', the next test candidate.	 */	g = (2*start_k) // Q;	tmp = 2*start_k - Q*g;	for (tmp2=0, hindx=0;	     hindx < hcount && (tmp2 += hset[hindx]/n) < tmp;	     ++hindx) {	}	if (hindx == hcount) {		/* we are beyond the end of a hset[] cycle, start at the next */		++g;		hindx = 0;		tmp2 = hset[0]/n;	}	q = (Q*g + tmp2)*n + 1;	/*	 * look for a factor	 *	 * We ignore factors that themselves are divisible by a prime <=	 * some small prime p.	 *	 * This process is guaranteed to find the smallest factor	 * of 2^n-1.  A smallest factor of 2^n-1 must be prime, otherwise	 * the divisors of that factor would also be factors of 2^n-1.	 * Thus we know that if a test factor itself is not prime, it	 * cannot be the smallest factor of 2^n-1.	 *	 * Eliminating all non-prime test factors would take too long.	 * However we can eliminate 80.81% of the test factors	 * by not using test factors that are divisible by a prime <= 17.	 */	if (pmod(2,n,q) == 1) {		return q;	} else {		/* report this loop */		printf("at 2*%d*%d+1, cpu: %f\n",			(q-1)/(2*n), n, usertime());		fflush(files(1));		loop = 0;	}	do {		/*		 * determine if we need to report		 *		 * NOTE: (q-1)/(2*n) is the k value from 2*k*n + 1.		 */		if (rept_loop <= ++loop) {			/* report this loop */			printf("at 2*%d*%d+1, cpu: %f\n",				(q-1)/(2*n), n, usertime());			fflush(files(1));			loop = 0;		}		/*		 * skip if divisable by a prime <= 449		 *		 * The value 281 was determined by timing loops		 * which found that 281 was at or near the		 * minimum time to factor 2^(2^127-1)-1.		 *		 * The addition of the do { ... } while (factor(q, 449)>1);		 * loop reduced the factoring loop time (36504 k values with		 * the hset[] initialization time removed) from 25.69 sec to		 * 15.62 sec of CPU time on a 200Mhz r4k.		 */		do {			/*			 * determine the next factor candidate			 */			q += hset[++hindx];			if (hindx >= hcount) {				hindx = 0;				/*				 * if we cared about g,				 * then we wound ++g here too				 */			}		} while (factor(q, 449) > 1);	} while (pmod(2,n,q) != 1);	/*	 * return the factor found	 *	 * q is a factor of (2^n)-1	 */	return q;}if (config("resource_debug") & 3) {	print "mfactor(n [, start_k=1 [, rept_loop=10000 [, p_elim=17]]])"}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -