/*--------------------------------------------------------------------
This source distribution is placed in the public domain by its author,
Jason Papadopoulos. You may use it for any purpose, free of charge,
without having to notify anyone. I disclaim any responsibility for any
errors.
Optionally, please be nice and tell me if you find this source to be
useful. Again optionally, if you add to the functionality present here
please consider making those additions public too, so that others may
benefit from your work.
--jasonp@boo.net 5/27/07
--------------------------------------------------------------------*/
#include <msieve.h>
#include <signal.h>
msieve_obj *g_curr_factorization = NULL;
/*--------------------------------------------------------------------*/
void handle_signal(int sig) {
msieve_obj *obj = g_curr_factorization;
printf("\nreceived signal %d; shutting down\n", sig);
if (obj && (obj->flags & MSIEVE_FLAG_SIEVING_IN_PROGRESS))
obj->flags |= MSIEVE_FLAG_STOP_SIEVING;
else
_exit(0);
}
/*--------------------------------------------------------------------*/
void get_random_seeds(uint32 *seed1, uint32 *seed2) {
uint32 tmp_seed1, tmp_seed2;
/* In a multithreaded program, every msieve object
should have two unique, non-correlated seeds
chosen for it */
#ifndef WIN32
FILE *rand_device = fopen("/dev/urandom", "r");
if (rand_device != NULL) {
/* Yay! Cryptographic-quality nondeterministic randomness! */
fread(&tmp_seed1, sizeof(uint32), (size_t)1, rand_device);
fread(&tmp_seed2, sizeof(uint32), (size_t)1, rand_device);
fclose(rand_device);
}
else
#endif
{
/* <Shrug> For everyone else, sample the current time,
the high-res timer (hopefully not correlated to the
current time), and the process ID. Multithreaded
applications should fold in the thread ID too */
uint64 high_res_time = read_clock();
tmp_seed1 = ((uint32)(high_res_time >> 32) ^
(uint32)time(NULL)) *
(uint32)getpid();
tmp_seed2 = (uint32)high_res_time;
}
/* The final seeds are the result of a multiplicative
hash of the initial seeds */
(*seed1) = tmp_seed1 * ((uint32)40499 * 65543);
(*seed2) = tmp_seed2 * ((uint32)40499 * 65543);
}
/*--------------------------------------------------------------------*/
void print_usage(char *progname) {
printf("\nMsieve v. %d.%02d\n", MSIEVE_MAJOR_VERSION,
MSIEVE_MINOR_VERSION);
printf("\nusage: %s [options] [one_number]\n", progname);
printf("\nnumbers starting with '0' are treated as octal,\n"
"numbers starting with '0x' are treated as hexadecimal\n");
printf("\noptions:\n"
" -s <name> save intermediate results to <name>\n"
" instead of the default %s\n"
" -l <name> append log information to <name>\n"
" instead of the default %s\n"
" -i <name> read one or more integers to factor from\n"
" <name> (default worktodo.ini) instead of\n"
" from the command line\n"
" -m manual mode: enter numbers via standard input\n"
" -q quiet: do not generate any log information,\n"
" only print any factors found\n"
" -d <min> deadline: if still sieving after <min>\n"
" minutes, shut down gracefully (default off)\n"
" -r <num> stop after finding <num> relations\n"
" -v verbose: write log information to screen\n"
" as well as to logfile\n"
" -t <num> use at most <num> threads\n\n"
" quadratic sieve options:\n"
" -c client: only perform sieving\n\n"
" number field sieve options:\n"
" -n use the number field sieve (97+ digits only;\n"
" performs all NFS tasks in order)\n"
" -nf <name> read from / write to NFS factor base file\n"
" <name> instead of the default %s\n"
" -np [X,Y] perform only NFS polynomial selection; if\n"
" specified, cover the range from X to Y\n"
" percent of the total polynomial search\n"
" space, inclusive (1<=X<Y<=100)\n"
" -ns [X,Y] perform only NFS sieving; if specified,\n"
" handle sieve lines X to Y inclusive\n"
" -nc perform only NFS combining (all phases)\n"
" -nc1 perform only NFS filtering\n"
" -nc2 perform only NFS linear algebra\n"
" -nc3 [X,Y] perform only NFS square root (compute \n"
" dependency numbers X through Y, 1<=X,Y<=64)\n",
MSIEVE_DEFAULT_SAVEFILE, MSIEVE_DEFAULT_LOGFILE,
MSIEVE_DEFAULT_NFS_FBFILE);
}
/*--------------------------------------------------------------------*/
void factor_integer(char *buf, uint32 flags,
char *savefile_name,
char *logfile_name,
char *nfs_fbfile_name,
uint32 *seed1, uint32 *seed2,
uint32 max_relations,
uint32 nfs_lower,
uint32 nfs_upper,
enum cpu_type cpu,
uint32 cache_size1,
uint32 cache_size2,
uint32 num_threads) {
char *int_start, *last;
msieve_obj *obj;
msieve_factor *factor;
/* point to the start of the integer or expression;
if the start point indicates no integer is present,
don't try to factor it :) */
last = strchr(buf, '\n');
if (last)
*last = 0;
int_start = buf;
while (*int_start && !isdigit(*int_start) &&
*int_start != '(' ) {
int_start++;
}
if (*int_start == 0)
return;
g_curr_factorization = msieve_obj_new(int_start, flags,
savefile_name, logfile_name,
nfs_fbfile_name,
*seed1, *seed2, max_relations,
nfs_lower, nfs_upper, cpu,
cache_size1, cache_size2,
num_threads);
if (g_curr_factorization == NULL) {
printf("factoring initialization failed\n");
return;
}
msieve_run(g_curr_factorization);
if (!(g_curr_factorization->flags & MSIEVE_FLAG_FACTORIZATION_DONE)) {
printf("\ncurrent factorization was interrupted\n");
exit(0);
}
/* If no logging is specified, at least print out the
factors that were found */
if (!(g_curr_factorization->flags & (MSIEVE_FLAG_USE_LOGFILE |
MSIEVE_FLAG_LOG_TO_STDOUT))) {
factor = g_curr_factorization->factors;
printf("\n");
printf("%s\n", buf);
while (factor != NULL) {
char *factor_type;
if (factor->factor_type == MSIEVE_PRIME)
factor_type = "p";
else if (factor->factor_type == MSIEVE_COMPOSITE)
factor_type = "c";
else
factor_type = "prp";
printf("%s%d: %s\n", factor_type,
(int32)strlen(factor->number),
factor->number);
factor = factor->next;
}
printf("\n");
}
/* save the current value of the random seeds, so that
the next factorization will pick up the pseudorandom
sequence where this factorization left off */
*seed1 = g_curr_factorization->seed1;
*seed2 = g_curr_factorization->seed2;
/* free the current factorization struct. The following
avoids a race condition in the signal handler */
obj = g_curr_factorization;
g_curr_factorization = NULL;
if (obj)
msieve_obj_free(obj);
}
#ifdef WIN32
DWORD WINAPI countdown_thread(LPVOID pminutes) {
DWORD minutes = *(DWORD *)pminutes;
if (minutes > 0x7fffffff / 60000)
minutes = 0; /* infinite */
Sleep(minutes * 60000);
raise(SIGINT);
return 0;
}
#else
void *countdown_thread(void *pminutes) {
uint32 minutes = *(uint32 *)pminutes;
if (minutes > 0xffffffff / 60)
minutes = 0xffffffff / 60; /* infinite */
sleep(minutes * 60);
raise(SIGINT);
return NULL;
}
#endif
/*--------------------------------------------------------------------*/
int main(int argc, char **argv) {
char buf[300];
uint32 seed1, seed2;
char *savefile_name = NULL;
char *logfile_name = NULL;
char *infile_name = "worktodo.ini";
char *nfs_fbfile_name = NULL;
uint32 flags;
char manual_mode = 0;
int i;
int32 deadline = 0;
uint32 max_relations = 0;
uint32 nfs_lower = 0;
uint32 nfs_upper = 0;
enum cpu_type cpu;
uint32 cache_size1;
uint32 cache_size2;
uint32 num_threads = 0;
get_cache_sizes(&cache_size1, &cache_size2);
cpu = get_cpu_type();
if (signal(SIGINT, handle_signal) == SIG_ERR) {
printf("could not install handler on SIGINT\n");
return -1;
}
if (signal(SIGTERM, handle_signal) == SIG_ERR) {
printf("could not install handler on SIGTERM\n");
return -1;
}
flags = MSIEVE_FLAG_USE_LOGFILE;
i = 1;
buf[0] = 0;
while (i < argc) {
if (argv[i][0] == (char)('-')) {
switch(tolower(argv[i][1])) {
case 'h':
case '?':
print_usage(argv[0]);
return 0;
case 'i':
case 's':
case 'l':
if (i + 1 < argc &&
argv[i+1][0] != '-') {
if (tolower(argv[i][1]) == 'i')
infile_name = argv[i+1];
else if (tolower(argv[i][1]) == 's')
savefile_name = argv[i+1];
else
logfile_name = argv[i+1];
i += 2;
}
else {
print_usage(argv[0]);
return -1;
}
break;
case 'm':
manual_mode = 1;
i++;
break;
case 'n':
if (argv[i][2] == 'p') {
flags |= MSIEVE_FLAG_NFS_POLY;
}
else if (argv[i][2] == 's') {
flags |= MSIEVE_FLAG_NFS_SIEVE;
}
else if (argv[i][2] == 'c') {
if (argv[i][3] == '1')
flags |= MSIEVE_FLAG_NFS_FILTER;
else if (argv[i][3] == '2')
flags |= MSIEVE_FLAG_NFS_LA;
else if (argv[i][3] == '3')
flags |= MSIEVE_FLAG_NFS_SQRT;
else if (argv[i][3] == 0)
flags |=
MSIEVE_FLAG_NFS_FILTER |
MSIEVE_FLAG_NFS_LA |
MSIEVE_FLAG_NFS_SQRT;
}
else if (argv[i][2] == 0) {
flags |= MSIEVE_FLAG_NFS_POLY |
MSIEVE_FLAG_NFS_SIEVE |
MSIEVE_FLAG_NFS_FILTER |
MSIEVE_FLAG_NFS_LA |
MSIEVE_FLAG_NFS_SQRT;
}
if (i + 1 < argc && argv[i+1][0] != '-') {
if (argv[i][2] == 'f') {
nfs_fbfile_name = argv[i+1];
i++;
}
else if ((argv[i][2] == 's' ||
argv[i][2] == 'c' ||
argv[i][2] == 'p') &&
strchr(argv[i+1], ',') !=
NULL ) {
char *tmp;
nfs_lower = strtoul(argv[i+1],
&tmp, 10);
tmp++;
nfs_upper = strtoul(tmp,
NULL, 10);
i++;
}
}
i++;
break;
case 'q':
flags &= ~(MSIEVE_FLAG_USE_LOGFILE |
MSIEVE_FLAG_LOG_TO_STDOUT);
i++;
break;
case 'd':
if (i + 1 < argc && isdigit(argv[i+1][0])) {
deadline = atol(argv[i+1]);
i += 2;
}
else {
print_usage(argv[0]);
return -1;
}
break;
case 'r':
if (i + 1 < argc && isdigit(argv[i+1][0])) {
max_relations = atol(argv[i+1]);
i += 2;
}
else {
print_usage(argv[0]);
return -1;
}
break;
case 't':
if (i + 1 < argc && isdigit(argv[i+1][0])) {
num_threads = atol(argv[i+1]);
i += 2;
}
else {
print_usage(argv[0]);
return -1;
}
break;
case 'c':
flags |= MSIEVE_FLAG_SKIP_QS_CYCLES;
i++;
break;
case 'v':
flags |= MSIEVE_FLAG_LOG_TO_STDOUT;
i++;
break;
default:
print_usage(argv[0]);
return -1;
}
}
else {
if (isdigit(argv[i][0]) || argv[i][0] == '(' )
strncpy(buf, argv[i], sizeof(buf));
i++;
}
}
get_random_seeds(&seed1, &seed2);
if (deadline) {
#ifdef WIN32
DWORD thread_id;
CreateThread(NULL, 0, countdown_thread,
&deadline, 0, &thread_id);
#else
pthread_t thread_id;
pthread_create(&thread_id, NULL,
countdown_thread, &deadline);
#endif
}
if (isdigit(buf[0]) || buf[0] == '(' ) {
factor_integer(buf, flags, savefile_name,
logfile_name, nfs_fbfile_name,
&seed1, &seed2,
max_relations,
nfs_lower, nfs_upper, cpu,
cache_size1, cache_size2,
num_threads);
}
else if (manual_mode) {
while (1) {
printf("\n\nnext number: ");
fflush(stdout);
buf[0] = 0;
fgets(buf, (int)sizeof(buf), stdin);
factor_integer(buf, flags, savefile_name,
logfile_name, nfs_fbfile_name,
&seed1, &seed2,
max_relations,
nfs_lower, nfs_upper, cpu,
cache_size1, cache_size2,
num_threads);
if (feof(stdin))
break;
}
}
else {
FILE *infile = fopen(infile_name, "r");
if (infile == NULL) {
printf("cannot open input file '%s'\n", infile_name);
return 0;
}
while (1) {
buf[0] = 0;
fgets(buf, (int)sizeof(buf), infile);
factor_integer(buf, flags, savefile_name,
logfile_name, nfs_fbfile_name,
&seed1, &seed2,
max_relations,
nfs_lower, nfs_upper, cpu,
cache_size1, cache_size2,
num_threads);
if (feof(infile))
break;
}
fclose(infile);
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1