示例#1
0
// BenOr algorithm
// Why not return true or false? - of course C was written by the dinosours and booleans did not exist
// during that era. :/
int getReducibilty(unsigned long val) {
  bits temp = bits_initlong(val);
  int degree = poly_degree(temp);
  bits one = bits_initlong(1l);
  int i = 1;

  for(; i <= degree/2; i++) {
    bits b = poly_reduceExp(temp, i);
    bits g = poly_gcd(temp, b);
    if (!eq(one, g))
      return 1;
  }
  return 0;
}
示例#2
0
文件: makefb.c 项目: pstach/gls
u_int32_t is_irreducible(mpzpoly_t poly, u_int32_t p)
{

	/* this uses Proposition 3.4.4 of H. Cohen, "A Course
	   in Computational Algebraic Number Theory". The tests
	   below are much simpler than trying to factor 'poly' */

	u_int32_t i;
	poly_t f, tmp;

	poly_reduce_mod_p(f, poly, p);
	poly_make_monic(f, f, p);

	/* in practice, the degree of f will be 8 or less,
	   and we want to compute GCDs for all prime numbers
	   that divide the degree. For this limited range
	   the loop below avoids duplicated code */

	for (i = 2; i < f->degree; i++) {
		if (f->degree % i)
			continue;

		/* for degree d, compute x^(p^(d/i)) - x */

		poly_xpow_pd(tmp, p, f->degree / i, f);
		if (tmp->degree == 0) {
			tmp->degree = 1;
			tmp->coef[1] = p - 1;
		}
		else {
			tmp->coef[1] = mp_modsub_1(tmp->coef[1],
						(u_int32_t)1, p);
			poly_fix_degree(tmp);
		}

		/* this must be relatively prime to f */

		poly_gcd(tmp, f, p);
		if (tmp->degree > 0 || tmp->coef[0] != 1) {
			return 0;
		}
	}

	/* final test: x^(p^d) mod f must equal x */

	poly_xpow_pd(tmp, p, f->degree, f);
	if (tmp->degree == 1 && tmp->coef[0] == 0 && tmp->coef[1] == 1)
		return 1;
	return 0;
}
示例#3
0
// retourne le degré du plus petit facteur
int poly_degppf(poly_t g) {
    int i, d, res;
    poly_t *u, p, r, s;

    d = poly_deg(g);
    u = malloc(d * sizeof (poly_t *));
    for (i = 0; i < d; ++i)
        u[i] = poly_alloc(d + 1);
    poly_sqmod_init(g, u);

    p = poly_alloc(d - 1);
    poly_set_deg(p, 1);
    poly_set_coeff(p, 1, gf_unit());
    r = poly_alloc(d - 1);
    res = d;
    for (i = 1; i <= (d / 2) * gf_extd(); ++i) {
        poly_sqmod(r, p, u, d);
        // r = x^(2^i) mod g
        if ((i % gf_extd()) == 0) { // donc 2^i = (2^m)^j (m deg d'extension)
            poly_addto_coeff(r, 1, gf_unit());
            poly_calcule_deg(r); // le degré peut changer
            s = poly_gcd(g, r);
            if (poly_deg(s) > 0) {
                poly_free(s);
                res = i / gf_extd();
                break;
            }
            poly_free(s);
            poly_addto_coeff(r, 1, gf_unit());
            poly_calcule_deg(r); // le degré peut changer
        }
        // on se sert de s pour l'échange
        s = p;
        p = r;
        r = s;
    }

    poly_free(p);
    poly_free(r);
    for (i = 0; i < d; ++i) {
        poly_free(u[i]);
    }
    free(u);

    return res;
}
示例#4
0
// Returns the degree of the smallest factor
int poly_degppf(poly_t g) {
  int i, d, res;
  poly_t *u, p, r, s;

  d = poly_deg(g);
  u = malloc(d * sizeof (poly_t *));
  for (i = 0; i < d; ++i)
    u[i] = poly_alloc(d + 1);
  poly_sqmod_init(g, u);

  p = poly_alloc(d - 1);
  poly_set_deg(p, 1);
  poly_set_coeff(p, 1, gf_unit());
  r = poly_alloc(d - 1);
  res = d;
  for (i = 1; i <= (d / 2) * gf_extd(); ++i) {
    poly_sqmod(r, p, u, d);
    // r = x^(2^i) mod g
    if ((i % gf_extd()) == 0) { // so 2^i = (2^m)^j (m ext. degree)
      poly_addto_coeff(r, 1, gf_unit());
      poly_calcule_deg(r); // The degree may change
      s = poly_gcd(g, r);
      if (poly_deg(s) > 0) {
	poly_free(s);
	res = i / gf_extd();
	break;
      }
      poly_free(s);
      poly_addto_coeff(r, 1, gf_unit());
      poly_calcule_deg(r); // The degree may change
    }
    // No need for the exchange s
    s = p;
    p = r;
    r = s;
  }

  poly_free(p);
  poly_free(r);
  for (i = 0; i < d; ++i) {
    poly_free(u[i]);
  }
  free(u);

  return res;
}
示例#5
0
文件: makefb.c 项目: pstach/gls
/*------------------------------------------------------------------*/
u_int32_t poly_get_zeros(u_int32_t *zeros, mpzpoly_t _f, u_int32_t p, u_int32_t count_only)
{
    /* Find all roots of multiplicity 1 for polynomial _f,
	   when the coefficients of _f are reduced mod p.
	   The leading coefficient of _f mod p is returned

	   Make count_only nonzero if only the number of roots
	   and not their identity matters; this is much faster */

	poly_t g, f;
	u_int32_t i, j, num_zeros;

	/* reduce the coefficients mod p */

	poly_reduce_mod_p(f, _f, p);

	/* bail out if the polynomial is zero */

	if (f->degree == 0)
		return 0;

	/* pull out roots of zero. We do this early to
	   avoid having to handle degree-1 polynomials
	   in later code */

	num_zeros = 0;
	if (f->coef[0] == 0) {
		for (i = 1; i <= f->degree; i++) {
			if (f->coef[i])
				break;
		}
		for (j = i; i <= f->degree; i++) {
			f->coef[i - j] = f->coef[i];
		}
		f->degree = i - j - 1;
		zeros[num_zeros++] = 0;
	}

	/* handle trivial cases */

	if (f->degree == 0) {
		return num_zeros;
	}
	else if (f->degree == 1) {
		u_int32_t w = f->coef[1];

		if (count_only)
			return num_zeros + 1;

		if (w != 1) {
			w = mp_modinv_1(w, p);
			zeros[num_zeros++] = mp_modmul_1(p - f->coef[0],
						w, p);
		}
		else {
			zeros[num_zeros++] = (f->coef[0] == 0 ?
						0 : p - f->coef[0]);
		}
		return num_zeros;
	}

	/* the rest of the algorithm assumes p is odd, which
	   will not work for p=2. Fortunately, in that case
	   there are only two possible roots, 0 and 1. The above
	   already tried 0, so try 1 here */

	if (p == 2) {
		u_int32_t parity = 0;
		for (i = 0; i <= f->degree; i++)
			parity ^= f->coef[i];
		if (parity == 0)
			zeros[num_zeros++] = 1;
		return num_zeros;
	}

	/* Compute g = gcd(f, x^(p-1) - 1). The result is
	   a polynomial that is the product of all the linear
	   factors of f. A given factor only occurs once in
	   this polynomial */

	poly_xpow(g, 0, p-1, f, p);
	g->coef[0] = mp_modsub_1(g->coef[0], 1, p);
	poly_fix_degree(g);
	poly_gcd(g, f, p);

	/* no linear factors, no service */

	if (g->degree < 1 || count_only)
		return num_zeros + g->degree;

	/* isolate the linear factors */

	get_zeros_rec(zeros, 0, &num_zeros, g, p);
	return num_zeros;
}
示例#6
0
文件: makefb.c 项目: pstach/gls
/*------------------------------------------------------------------*/
static void get_zeros_rec(u_int32_t *zeros, u_int32_t shift,
			u_int32_t *num_zeros, poly_t f, u_int32_t p) {

	/* get the zeros of a poly, f, that is known to split
	   completely over Z/pZ. Many thanks to Bob Silverman
	   for a neat implementation of Cantor-Zassenhaus splitting */

	poly_t g, xpow;
	u_int32_t degree1, degree2;

	/* base cases of the recursion: we can find the roots
	   of linear and quadratic polynomials immediately */

	if (f->degree == 1) {
		u_int32_t w = f->coef[1];
		if (w != 1) {
			w = mp_modinv_1(w, p);
			zeros[(*num_zeros)++] = mp_modmul_1(p - f->coef[0],w,p);
		}
		else {
			zeros[(*num_zeros)++] = (f->coef[0] == 0 ? 0 :
							p - f->coef[0]);
		}
		return;
	}
	else if (f->degree == 2) {

		/* if f is a quadratic polynomial, then it will
		   always have two distinct nonzero roots or else
		   we wouldn't have gotten to this point. The two
		   roots are the solution of a general quadratic
		   equation, mod p */

		u_int32_t d = mp_modmul_1(f->coef[0], f->coef[2], p);
		u_int32_t root1 = p - f->coef[1];
		u_int32_t root2 = root1;
		u_int32_t ainv = mp_modinv_1(
				mp_modadd_1(f->coef[2], f->coef[2], p),
				p);

		d = mp_modsub_1(mp_modmul_1(f->coef[1], f->coef[1], p),
				mp_modmul_1(4, d, p),
				p);
		d = mp_modsqrt_1(d, p);

		root1 = mp_modadd_1(root1, d, p);
		root2 = mp_modsub_1(root2, d, p);
		zeros[(*num_zeros)++] = mp_modmul_1(root1, ainv, p);
		zeros[(*num_zeros)++] = mp_modmul_1(root2, ainv, p);
		return;
	}

	/* For an increasing sequence of integers 's', compute
	   the polynomial gcd((x-s)^(p-1)/2 - 1, f). If the result is
	   not g = 1 or g = f, this is a nontrivial splitting
	   of f. References require choosing s randomly, but however
	   s is chosen there is a 50% chance that it will split f.
	   Since only 0 <= s < p is valid, we choose each s in turn;
	   choosing random s allows the possibility that the same
	   s gets chosen twice (mod p), which would waste time */

	while (shift < p) {
		poly_xpow(xpow, shift, (p-1)/2, f, p);

		poly_cp(g, xpow);
		g->coef[0] = mp_modsub_1(g->coef[0], 1, p);
		poly_fix_degree(g);

		poly_gcd(g, f, p);

		if (g->degree > 0)
			break;
		shift++;
	}

	/* f was split; repeat the splitting process on
	   the two halves of f. The linear factors of f are
	   either somewhere in x^((p-1)/2) - 1, in
	   x^((p-1)/2) + 1, or 'shift' itself is a linear
	   factor. Test each of these possibilities in turn.
	   In the first two cases, begin trying values of s
	   strictly greater than have been tried thus far */

	degree1 = g->degree;
	get_zeros_rec(zeros, shift + 1, num_zeros, g, p);

	poly_cp(g, xpow);
	g->coef[0] = mp_modadd_1(g->coef[0], 1, p);
	poly_fix_degree(g);
	poly_gcd(g, f, p);
	degree2 = g->degree;

	if (degree2 > 0)
		get_zeros_rec(zeros, shift + 1, num_zeros, g, p);

	if (degree1 + degree2 < f->degree)
		zeros[(*num_zeros)++] = (shift == 0 ? 0 : p - shift);
}