diff --git a/src/qsieve.h b/src/qsieve.h index 5e4b76af12..4c88ceacc6 100644 --- a/src/qsieve.h +++ b/src/qsieve.h @@ -167,8 +167,10 @@ typedef struct RELATION DATA ***************************************************************************/ - FLINT_FILE * siqs; /* pointer to file for storing relations */ - char * fname; /* name of file used for relations */ + char * siqs; /* pointer to storage */ + char * siqs_cur; /* pointer to current position in storage */ + slong siqs_alloc; /* number of bytes allocated */ + slong siqs_size; /* number of bytes used */ slong full_relation; /* number of full relations */ slong num_cycles; /* number of possible full relations from partials */ @@ -420,6 +422,100 @@ uint64_t * block_lanczos(flint_rand_t state, slong nrows, void qsieve_square_root(fmpz_t X, fmpz_t Y, qs_t qs_inf, uint64_t * nullrows, slong ncols, slong l, fmpz_t N); +#define QS_SIQS_SIZE_LEFT(qs_inf) ((slong) ((qs_inf)->siqs + (qs_inf)->siqs_size - (qs_inf)->siqs_cur)) +#define QS_SIQS_ALLOC_LEFT(qs_inf) ((slong) ((qs_inf)->siqs + (qs_inf)->siqs_alloc - (qs_inf)->siqs_cur)) + +#define QS_SIQS_INIT_ALLOC_SIZE (sizeof(char) * (WORD(1) << 25)) /* 32 MB */ + +#define QS_SIQS_INIT(qs_inf) \ +do \ +{ \ + (qs_inf)->siqs = flint_malloc(QS_SIQS_INIT_ALLOC_SIZE); \ + /* Do not set (qs_inf)->siqs_cur */ \ + (qs_inf)->siqs_alloc = QS_SIQS_INIT_ALLOC_SIZE; \ + (qs_inf)->siqs_size = 0; \ +} while (0) +#define QS_SIQS_REALLOC(qs_inf, size) \ +do \ +{ \ + char * __tmp = flint_realloc((qs_inf)->siqs, size); \ + (qs_inf)->siqs_cur = __tmp + ((qs_inf)->siqs_cur - (qs_inf)->siqs); \ + (qs_inf)->siqs = __tmp; \ + (qs_inf)->siqs_alloc = (size); \ +} while (0) +#define QS_SIQS_CLEAR(qs_inf) \ +do \ +{ \ + flint_free((qs_inf)->siqs); \ + (qs_inf)->siqs = NULL; \ + /* Do not clear (qs_inf)->siqs_cur */ \ + (qs_inf)->siqs_alloc = 0; \ + (qs_inf)->siqs_size = 0; \ +} while (0) + +#define QS_SIQS_FCLOSE(qs_inf) \ +do \ +{ \ + (qs_inf)->siqs_cur = NULL; \ +} while (0) +#define QS_SIQS_FOPEN_R(qs_inf) \ +do \ +{ \ + (qs_inf)->siqs_cur = (qs_inf)->siqs; \ +} while (0) +#define QS_SIQS_FOPEN_W(qs_inf) \ +do \ +{ \ + (qs_inf)->siqs_cur = (qs_inf)->siqs; \ + (qs_inf)->siqs_size = 0; \ +} while (0) +#define QS_SIQS_FOPEN_A(qs_inf) \ +do \ +{ \ + (qs_inf)->siqs_cur = (qs_inf)->siqs + (qs_inf)->siqs_size; \ +} while (0) + +#define QS_SIQS_FREAD(res, ptr, size, count, qs_inf) \ +do \ +{ \ + slong _max_read \ + = FLINT_MIN((slong) (size) * (slong) (count), \ + QS_SIQS_SIZE_LEFT(qs_inf)); \ + \ + memcpy(ptr, (qs_inf)->siqs_cur, _max_read); \ + (qs_inf)->siqs_cur += _max_read; \ + (res) = _max_read; \ +} while (0) +#define QS_SIQS_FREAD_NORES(ptr, size, count, qs_inf) \ +do \ +{ \ + slong __useless; \ + QS_SIQS_FREAD(__useless, ptr, size, count, qs_inf); \ +} while (0) +#define QS_SIQS_FWRITE(ptr, size, count, qs_inf) \ +do \ +{ \ + slong _write_size = (slong) (size) * (slong) (count); \ + \ + /* Here we assume that the relation size is always */ \ + /* less than QS_SIQS_INIT_ALLOC_SIZE */ \ + if (_write_size > QS_SIQS_ALLOC_LEFT(qs_inf)) \ + QS_SIQS_REALLOC(qs_inf, 2 * (qs_inf)->siqs_alloc); \ + \ + memcpy((qs_inf)->siqs_cur, ptr, _write_size); \ + (qs_inf)->siqs_cur += _write_size; \ + (qs_inf)->siqs_size += _write_size; \ +} while (0) + +#define QS_SIQS_FSEEK_SEEK_CUR(qs_inf, offset) \ +do \ +{ \ + slong _jump_size \ + = FLINT_MIN((slong) (offset), QS_SIQS_SIZE_LEFT(qs_inf)); \ + \ + (qs_inf)->siqs_cur += _jump_size; \ +} while (0) + #ifdef __cplusplus } #endif diff --git a/src/qsieve/clear.c b/src/qsieve/clear.c index edfba23fbb..8b70af3ef7 100644 --- a/src/qsieve/clear.c +++ b/src/qsieve/clear.c @@ -23,6 +23,4 @@ void qsieve_clear(qs_t qs_inf) qs_inf->factor_base = NULL; qs_inf->sqrts = NULL; - - flint_free(qs_inf->fname); } diff --git a/src/qsieve/factor.c b/src/qsieve/factor.c index c815a72862..36a5c74a5f 100644 --- a/src/qsieve/factor.c +++ b/src/qsieve/factor.c @@ -11,32 +11,14 @@ (at your option) any later version. See . */ -#define _STDC_FORMAT_MACROS - -#ifdef __GNUC__ -# define strcpy __builtin_strcpy -#else -# include -#endif - -/* try to get fdopen, mkstemp declared */ -#if defined __STRICT_ANSI__ -#undef __STRICT_ANSI__ -#endif - -#include #include +#include #include "thread_support.h" #include "fmpz.h" #include "fmpz_factor.h" #include "fmpz_vec.h" #include "qsieve.h" -/* Use Windows API for temporary files under MSVC and MinGW */ -#if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) -#include -#endif - int compare_facs(const void * a, const void * b) { fmpz * x = (fmpz *) a; @@ -63,11 +45,6 @@ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) fmpz_t temp, temp2, X, Y; slong num_facs; fmpz * facs; -#if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) - char temp_path[MAX_PATH]; -#else - int fd; -#endif if (fmpz_sgn(n) < 0) { @@ -214,41 +191,8 @@ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) pthread_mutex_init(&qs_inf->mutex, NULL); #endif -#if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) - if (GetTempPathA(MAX_PATH, temp_path) == 0) - { - flint_printf("Exception (qsieve_factor). GetTempPathA() failed.\n"); - flint_abort(); - } - /* uUnique = 0 means the we *do* want a unique filename (obviously!). */ - if (GetTempFileNameA(temp_path, "siq", /*uUnique*/ 0, qs_inf->fname) == 0) - { - flint_printf("Exception (qsieve_factor). GetTempFileNameA() failed.\n"); - flint_abort(); - } - qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "wb"); - if (qs_inf->siqs == NULL) - flint_throw(FLINT_ERROR, "fopen failed\n"); -#else - strcpy(qs_inf->fname, "/tmp/siqsXXXXXX"); /* must be shorter than fname_alloc_size in init.c */ - fd = mkstemp(qs_inf->fname); - if (fd == -1) - flint_throw(FLINT_ERROR, "mkstemp failed\n"); - - qs_inf->siqs = (FLINT_FILE *) fdopen(fd, "wb"); - if (qs_inf->siqs == NULL) - flint_throw(FLINT_ERROR, "fdopen failed\n"); -#endif - /* - * The code here and in large_prime_variant.c opens and closes the file - * qs_inf->fname in several different places. On Windows all file handles - * need to be closed before the file can be removed in cleanup at function - * exit. The invariant that needs to be preserved at each open/close is - * that either - * qs_inf->siqs is NULL and there are no open handles to the file, - * or - * qs_inf->siqs is not NULL and is the *only* open handle to the file. - */ + QS_SIQS_INIT(qs_inf); + QS_SIQS_FOPEN_W(qs_inf); for (j = qs_inf->small_primes; j < qs_inf->num_primes; j++) { @@ -290,9 +234,7 @@ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) { int ok; - if (fclose((FILE *) qs_inf->siqs)) - flint_throw(FLINT_ERROR, "fclose fail\n"); - qs_inf->siqs = NULL; + QS_SIQS_FCLOSE(qs_inf); ok = qsieve_process_relation(qs_inf); @@ -406,9 +348,7 @@ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) _fmpz_vec_clear(facs, 100); - qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "wb"); - if (qs_inf->siqs == NULL) - flint_throw(FLINT_ERROR, "fopen fail\n"); + QS_SIQS_FOPEN_W(qs_inf); qs_inf->num_primes = num_primes; /* linear algebra adjusts this */ goto more_primes; /* factoring failed, may need more primes */ } @@ -486,11 +426,8 @@ void qsieve_factor(fmpz_factor_t factors, const fmpz_t n) flint_give_back_threads(qs_inf->handles, qs_inf->num_handles); flint_free(sieve); - if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) - flint_throw(FLINT_ERROR, "fclose fail\n"); - if (remove(qs_inf->fname)) { - flint_throw(FLINT_ERROR, "remove fail\n"); - } + QS_SIQS_FCLOSE(qs_inf); + QS_SIQS_CLEAR(qs_inf); qsieve_clear(qs_inf); qsieve_linalg_clear(qs_inf); qsieve_poly_clear(qs_inf); diff --git a/src/qsieve/init.c b/src/qsieve/init.c index 1c5b162a27..2efc6933f1 100644 --- a/src/qsieve/init.c +++ b/src/qsieve/init.c @@ -13,22 +13,10 @@ #include "fmpz.h" #include "qsieve.h" -#if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) -#include -#endif - void qsieve_init(qs_t qs_inf, const fmpz_t n) { - size_t fname_alloc_size; slong i; -#if (defined(__WIN32) && !defined(__CYGWIN__)) || defined(_MSC_VER) - fname_alloc_size = MAX_PATH; -#else - fname_alloc_size = 20; -#endif - qs_inf->fname = (char *) flint_malloc(fname_alloc_size); /* space for filename */ - /* store n in struct */ fmpz_init_set(qs_inf->n, n); diff --git a/src/qsieve/large_prime_variant.c b/src/qsieve/large_prime_variant.c index 9c18c4f702..cd5ece4cb0 100644 --- a/src/qsieve/large_prime_variant.c +++ b/src/qsieve/large_prime_variant.c @@ -10,18 +10,12 @@ (at your option) any later version. See . */ -#include #include +#include #include #include "fmpz.h" #include "qsieve.h" -#ifdef __GNUC__ -# define memset __builtin_memset -#else -# include -#endif - #define HASH_MULT (2654435761U) /* hash function, taken from 'msieve' */ #define HASH(a) ((ulong)((((unsigned int) a) * HASH_MULT) >> (12))) @@ -131,26 +125,26 @@ void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, const fmpz_t Y, const qs + sizeof(fac_t) * num_factors /* factors */ + sizeof(slong) /* Y->_mp_size */ + sizeof(mp_limb_t) * (Ysz != 0 ? FLINT_ABS(Ysz) : 1); /* Y->_mp_d */ - fwrite(&write_size, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&write_size, sizeof(slong), 1, qs_inf); /* Write large prime */ - fwrite(&prime, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&prime, sizeof(mp_limb_t), 1, qs_inf); /* NOTE: We do not have to write small primes. */ /* Write number of small primes */ - fwrite(&qs_inf->small_primes, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&qs_inf->small_primes, sizeof(slong), 1, qs_inf); /* Write small primes */ - fwrite(small, sizeof(slong), qs_inf->small_primes, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(small, sizeof(slong), qs_inf->small_primes, qs_inf); /* Write number of factors */ - fwrite(&num_factors, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&num_factors, sizeof(slong), 1, qs_inf); /* Write factors and exponents */ - fwrite(factor, sizeof(fac_t), num_factors, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(factor, sizeof(fac_t), num_factors, qs_inf); /* Write Y->_mp_size (or mock it) */ - fwrite(&Ysz, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&Ysz, sizeof(slong), 1, qs_inf); /* Write Y->_mp_d (or mock it) */ if (!COEFF_IS_MPZ(*Y)) @@ -158,14 +152,14 @@ void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, const fmpz_t Y, const qs slong abslimb = FLINT_ABS(*Y); /* Write mock Y->_mp_d */ - fwrite(&abslimb, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(&abslimb, sizeof(mp_limb_t), 1, qs_inf); } else { mp_srcptr Yd = COEFF_TO_PTR(*Y)->_mp_d; /* Write Y->_mp_d */ - fwrite(Yd, sizeof(mp_limb_t), FLINT_ABS(Ysz), (FILE *) qs_inf->siqs); + QS_SIQS_FWRITE(Yd, sizeof(mp_limb_t), FLINT_ABS(Ysz), qs_inf); } } @@ -264,22 +258,22 @@ relation_t qsieve_parse_relation(qs_t qs_inf) /* NOTE: We can use qs_inf->small_primes here instead of reading. */ /* Get number of small primes */ - fread(&rel.small_primes, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(&rel.small_primes, sizeof(slong), 1, qs_inf); /* Get small primes */ rel.small = flint_malloc(rel.small_primes * sizeof(slong)); - fread(rel.small, sizeof(slong), rel.small_primes, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(rel.small, sizeof(slong), rel.small_primes, qs_inf); /* Get number of factors */ - fread(&rel.num_factors, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(&rel.num_factors, sizeof(slong), 1, qs_inf); /* Get factors */ rel.factor = flint_malloc(rel.num_factors * sizeof(fac_t)); - fread(rel.factor, sizeof(fac_t), rel.num_factors, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(rel.factor, sizeof(fac_t), rel.num_factors, qs_inf); /* Get Ysz */ Ysz = 0; - fread(&Ysz, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(&Ysz, sizeof(slong), 1, qs_inf); /* Get Y */ fmpz_init(rel.Y); @@ -287,7 +281,7 @@ relation_t qsieve_parse_relation(qs_t qs_inf) { mp_limb_t abslimb = 0; - fread(&abslimb, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(&abslimb, sizeof(mp_limb_t), 1, qs_inf); #if COEFF_MAX != -COEFF_MIN # error @@ -305,7 +299,7 @@ relation_t qsieve_parse_relation(qs_t qs_inf) if (mY->_mp_alloc < FLINT_ABS(Ysz)) _mpz_realloc(mY, FLINT_ABS(Ysz)); - fread(mY->_mp_d, sizeof(mp_limb_t), FLINT_ABS(Ysz), (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(mY->_mp_d, sizeof(mp_limb_t), FLINT_ABS(Ysz), qs_inf); *rel.Y = PTR_TO_COEFF(mY); } @@ -557,11 +551,8 @@ int qsieve_process_relation(qs_t qs_inf) relation_t * rlist; int done = 0; - if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) - flint_throw(FLINT_ERROR, "fclose fail\n"); - qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "rb"); - if (qs_inf->siqs == NULL) - flint_throw(FLINT_ERROR, "fopen fail\n"); + QS_SIQS_FCLOSE(qs_inf); + QS_SIQS_FOPEN_R(qs_inf); #if QS_DEBUG & 64 flint_printf("Getting relations\n"); @@ -569,15 +560,15 @@ int qsieve_process_relation(qs_t qs_inf) while (1) { - int siqs_eof; - slong write_size = 0; + int read_size; + slong relation_size = 0; - siqs_eof = !fread(&write_size, sizeof(slong), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD(read_size, &relation_size, sizeof(slong), 1, qs_inf); - if (siqs_eof) + if (read_size != sizeof(slong)) break; - fread(&prime, sizeof(mp_limb_t), 1, (FILE *) qs_inf->siqs); + QS_SIQS_FREAD_NORES(&prime, sizeof(mp_limb_t), 1, qs_inf); entry = qsieve_get_table_entry(qs_inf, prime); if (num_relations == rel_size) @@ -596,13 +587,11 @@ int qsieve_process_relation(qs_t qs_inf) { /* We have to get to the next relation in the file. We have already * read write_size (is a slong) and large prime (is an mp_limb_t).*/ - fseek((FILE *) qs_inf->siqs, write_size - sizeof(slong) - sizeof(mp_limb_t), SEEK_CUR); + QS_SIQS_FSEEK_SEEK_CUR(qs_inf, relation_size - sizeof(slong) - sizeof(mp_limb_t)); } } - if(fclose((FILE *) qs_inf->siqs)) - flint_throw(FLINT_ERROR, "fclose fail\n"); - qs_inf->siqs = NULL; + QS_SIQS_FCLOSE(qs_inf); #if QS_DEBUG & 64 flint_printf("Removing duplicates\n"); @@ -655,11 +644,8 @@ int qsieve_process_relation(qs_t qs_inf) { qs_inf->edges -= 100; done = 0; - if (qs_inf->siqs != NULL && fclose((FILE *) qs_inf->siqs)) - flint_throw(FLINT_ERROR, "fclose fail\n"); - qs_inf->siqs = (FLINT_FILE *) fopen(qs_inf->fname, "ab"); - if (qs_inf->siqs == NULL) - flint_throw(FLINT_ERROR, "fopen fail\n"); + QS_SIQS_FCLOSE(qs_inf); + QS_SIQS_FOPEN_A(qs_inf); } else { done = 1;