/*--------------------------------------------------------------------
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 6/3/07
--------------------------------------------------------------------*/

#include <common.h>
#include "mpqs.h"

/*--------------------------------------------------------------------*/
uint32 find_factors(msieve_obj *obj, mp_t *n, 
		fb_t *factor_base, uint32 fb_size,
		la_col_t *vectors, uint32 vsize, 
		relation_t *relation_list,
		uint64 *null_vectors, uint32 multiplier,
		mp_t *poly_a_list, poly_t *poly_list,
		factor_list_t *factor_list) {

	/* Perform the square root phase of MPQS. null_vectors
	   contains 64 linear dependencies of the relations in
	   vectors[], which has vsize elements. The code constructs
	   two numbers X and Y (mod n) that are each the product
	   of a huge number of factors derived from vectors[]. It
	   then computes gcd(X+-Y, n) for each linear dependency.
	   gcd values that are not 1 or n are a nontrivial factor
	   of n (or a product of nontrivial factors). For n the
	   product of two prime factors this will happen 2/3 of the 
	   time per dependency, on average.
	   
	   More specifically, vectors[] is a list of relations,
	   each of the form

   	   (a[i] * x[i] + b[i])^2 = prod(factors[i][]) mod n

	   X is a product of the (a[i] * x[i] + b[i]) and Y is
	   the product of sqrt(prod(factors[i][])), both mod n. 
	   The code never needs to calculate explicit square roots, 
	   because it knows the complete factorization of Y. Whether 
	   relation i contributes to dependency j is determined by 
	   the value of the j_th bit of null_vectors[i].

	   Because this implementation uses the double large prime
	   variation of MPQS, a single relation can actually be composed
	   of the product of several entities of the above form. In that
	   case, all entities are multiplied into X and Y (or all
	   are skipped).

	   Note that the code doesn't stop with one nontrivial
	   factor; it prints them all. If you go to so much work
	   and the other dependencies are there for free, why not
	   use them? */

	mp_t factor, x, y, tmp, sum;
	uint32 i, j, k, m;
	uint64 mask;
	uint32 *fb_counts;
	uint32 large_primes[200], num_large_primes;
	uint32 num_relations, prime;
	relation_t *relation;
	uint32 factor_found = 0;

	fb_counts = (uint32 *)malloc(fb_size * sizeof(uint32));
	mp_clear(&factor);
	factor.nwords = 1;

	/* For each dependency */

	for (mask = 1; mask; mask <<= 1) {
		memset(fb_counts, 0, fb_size * sizeof(uint32));
		mp_clear(&x);
		mp_clear(&y);
		x.nwords = y.nwords = x.val[0] = y.val[0] = 1;

		/* For each sieve relation */

		for (i = 0; i < vsize; i++) {

			/* If the relation is not scheduled to
			   contribute to x and y, skip it */

			if (!(null_vectors[i] & mask))
				continue;
			
			/* compute the number of sieve_values */

			num_large_primes = 0;
			num_relations = vectors[i].cycle.num_relations;

			/* for all sieve values */

			for (j = 0; j < num_relations; j++) {
				mp_t *a, *b;
				poly_t *poly;
				uint32 sieve_offset;
				uint32 sign_of_index;

				relation = relation_list + 
						vectors[i].cycle.list[j];
				
				/* reconstruct a[i], b[i], x[i] and
				   the sign of x[i]. Drop the subscript
				   from here on. */

				poly = poly_list + relation->poly_idx;
				b = &poly->b;
				a = poly_a_list + poly->a_idx;
				sieve_offset = relation->sieve_offset & 
								0x7fffffff;
				sign_of_index = relation->sieve_offset >> 31;

				/* Form (a * sieve_offset + b). Note that 
				   sieve_offset can be negative; in that
				   case the minus sign is implicit. We don't
				   have to normalize mod n because there
				   are an even number of negative values
				   to multiply together */
	
				mp_mul_1(a, sieve_offset, &sum);
				if (sign_of_index == POSITIVE)
					mp_add(&sum, b, &sum);
				else
					mp_sub(&sum, b, &sum);
	
				/* multiply the sum into x */
	
				mp_modmul(&x, &sum, n, &x);
	
				/* do not multiply the factors associated 
				   with this relation into y; instead, just 
				   update the count for each factor base 
				   prime. Unlike ordinary MPQS, the list
				   of factors is for the complete factor-
				   ization of a*(a*x^2+b*x+c), so the 'a' 
				   in front need not be treated separately */
	
				for (k = 0; k < relation->num_factors; k++)
					fb_counts[relation->fb_offsets[k]]++;
					
				/* if the sieve value contains one or more
				   large primes, accumulate them in a 
				   dedicated table. Do not multiply them
				   into y until all of the sieve values
				   for this relation have been processed */

				for (k = 0; k < 2; k++) {
					prime = relation->large_prime[k];
					if (prime == 1)
						continue;

					for (m = 0; m < num_large_primes; m++) {
						if (prime == large_primes[2*m]){
							large_primes[2*m+1]++;
							break;
						}
					}
					if (m == num_large_primes) {
						large_primes[2*m] = prime;
						large_primes[2*m+1] = 1;
						num_large_primes++;
					}
				}
			}

			for (j = 0; j < num_large_primes; j++) {
				for (k = 0; k < large_primes[2*j+1]/2; k++) {
					factor.val[0] = large_primes[2*j];
					mp_modmul(&y, &factor, n, &y);
				}
			}
		}

		/* For each factor base prime p, compute 
			p ^ ((number of times p occurs in y) / 2) mod n
		   then multiply it into y. This is enormously
		   more efficient than multiplying by one p at a time */

		for (i = MIN_FB_OFFSET; i < fb_size; i++) {
			uint32 mask2 = 0x80000000;
			uint32 exponent = fb_counts[i] / 2;
			uint32 prime = factor_base[i].prime;

			if (exponent == 0)
				continue;

			mp_clear(&tmp);
			tmp.nwords = 1;
			tmp.val[0] = factor_base[i].prime; 
			factor.val[0] = prime;

			while (!(exponent & mask2))
				mask2 >>= 1;
			for (mask2 >>= 1; mask2; mask2 >>= 1) {
				mp_modmul(&tmp, &tmp, n, &tmp);
				if (exponent & mask2) {
					mp_modmul(&tmp, &factor, n, &tmp);
				}
			}
			mp_modmul(&tmp, &y, n, &y);
		}

		/* compute gcd(x+y, n). If it's not 1 or n, save it 
		   (and stop processing dependencies if the product 
		   of all the probable prime factors found so far equals 
		   n). See the comments in Pari's MPQS code for a proof 
		   that it isn't necessary to also check gcd(x-y, n) */

		mp_add(&x, &y, &tmp);
		mp_gcd(&tmp, n, &tmp);
		if (mp_cmp(&tmp, n) != 0 && !mp_is_one(&tmp)) {

			/* remove any factors of the multiplier 
			   before saving tmp, and don't save at all
			   if tmp contains *only* multiplier factors */

			if (multiplier > 1) {
				uint32 ignore_me = mp_gcd_1(multiplier,
						mp_mod_1(&tmp, multiplier));
				if (ignore_me > 1) {
					mp_divrem_1(&tmp, ignore_me, &tmp);
					if (mp_is_one(&tmp))
						continue;
				}
			}

			factor_found = 1;
			if (factor_list_add(obj, factor_list, &tmp) == 0)
				break;
		}
	}

	free(fb_counts);
	return factor_found;
}



syntax highlighted by Code2HTML, v. 0.9.1