Пример #1
0
/**
 * Takes two (primitive) coefficients over the same variable, makes them univariate by
 * substituting 0 for other variables (if any). Then it computes the
 * univariate gcd of these. If the coefficients were univariate already, or
 * the result is a constant (i.e. gcd = 1), the result is precise.
 */
int coefficient_gcd_pp_univariate(const lp_polynomial_context_t* ctx,
    coefficient_t* gcd, const coefficient_t* C1, const coefficient_t* C2) {

  assert(C1->type == COEFFICIENT_POLYNOMIAL);
  assert(C2->type == COEFFICIENT_POLYNOMIAL);

  if (trace_is_enabled("coefficient")) {
    tracef("coefficient_gcd_pp_univariate()\n");
    tracef("C1 = "); coefficient_print(ctx, C1, trace_out); tracef("\n");
    tracef("C2 = "); coefficient_print(ctx, C2, trace_out); tracef("\n");
  }

  int C1_vanishes = integer_is_zero(ctx->K, coefficient_get_constant(coefficient_lc(C1)));
  int C2_vanishes = integer_is_zero(ctx->K, coefficient_get_constant(coefficient_lc(C2)));

  if (C1_vanishes || C2_vanishes) {
    // One of C1 or C2 vanishes in the univariate conversion, we're not precise enough
    return 0;
  }

  lp_variable_t x = VAR(C1);
  assert(x == VAR(C2));

  lp_upolynomial_t* C1_u = coefficient_to_univariate(ctx, C1);
  lp_upolynomial_t* C2_u = coefficient_to_univariate(ctx, C2);
  lp_upolynomial_t* gcd_u = lp_upolynomial_gcd(C1_u, C2_u);

  coefficient_t gcd_tmp;
  coefficient_construct_from_univariate(ctx, &gcd_tmp, gcd_u, x);
  coefficient_swap(&gcd_tmp, gcd);
  coefficient_destruct(&gcd_tmp);

  lp_upolynomial_delete(C1_u);
  lp_upolynomial_delete(C2_u);
  lp_upolynomial_delete(gcd_u);

  if (trace_is_enabled("coefficient")) {
    tracef("coefficient_gcd_pp_univariate() => ");
    tracef("gcd = "); coefficient_print(ctx, gcd, trace_out); tracef("\n");
  }

  if (gcd->type == COEFFICIENT_NUMERIC) {
    integer_assign_int(ctx->K, &gcd->value.num, 1);
    return 1;
  } else if (coefficient_is_univariate(C1) && coefficient_is_univariate(C2)) {
    return 1;
  } else {
    return 0;
  }
}
Пример #2
0
void monomial_gcd_visit(const lp_polynomial_context_t* ctx, lp_monomial_t* m, void* data) {
  lp_monomial_t* gcd = (lp_monomial_t*) data;
  if (integer_is_zero(ctx->K, &gcd->a)) {
    lp_monomial_assign(ctx, gcd, m, 0);
  } else {
    lp_monomial_gcd(ctx, gcd, gcd, m);
  }
}
Пример #3
0
int integer_square(integer_t target, integer_t source) {
  bool aliased;
  integer_t result;
  
  if(integer_is_zero(source)) { return integer_set_unsigned_value(target, 0); }
  
  aliased = (result == source);
  result = aliased ? integer_create(0) : target;

  VERIFY(GROW(result, 2 * LENGTH(source)));
  SET_SIGNED_LENGTH(result, 2 * LENGTH(source));

  VERIFY(digits_square(DIGITS(result), DIGITS(source), LENGTH(source)));
  NORMALIZE(result);

  // TODO: call a karatsuba routine here...

  if(aliased) {
    EXCHANGE(target, result);
    integer_destroy(result);
  }

  return 0;  
}
Пример #4
0
// MCA: ExtendedGCD
int integer_gcd_extended(integer_t gcd, integer_t U, integer_t V, integer_t A, integer_t B) {
  integer_t a, b, u, w, v, x, q, r;
  
  INSIST(gcd != U);
  INSIST(gcd != V);
  INSIST(U != V);

  a = integer_create(0);
  b = gcd;

  VERIFY(integer_absolute_value(a, A));
  VERIFY(integer_absolute_value(b, B));

  u = U;
  VERIFY(integer_set_unsigned_value(u, 1));
  w = integer_create(0);

  v = V;
  VERIFY(integer_set_unsigned_value(v, 0));
  x = integer_create(1);

  q = integer_create(0);
  r = integer_create(0);

  while(!integer_is_zero(b)) {
    VERIFY(integer_divide(q, r, a, b));
    SWAP(a, b);
    SWAP(b, r);

    VERIFY(integer_multiply(r, q, w));
    VERIFY(integer_subtract(u, u, r));
    SWAP(u, w);

    VERIFY(integer_multiply(r, q, x));
    VERIFY(integer_subtract(v, v, r));
    SWAP(v, x);
  }

  EXCHANGE(gcd, a);
  EXCHANGE(U, u);
  EXCHANGE(V, v);

  integer_destroy(q);
  /* gcd is passed between a, b, and r */
  if(b == gcd) {
    integer_destroy(a);
    integer_destroy(r);
  }
  else if(a == gcd) {
    integer_destroy(b);
    integer_destroy(r);
  }
  else {
    integer_destroy(a);
    integer_destroy(b);
  }
  
  /* U and V are passed between u, w and v, x respectively */
  if(u == U) {
    integer_destroy(w);
    integer_destroy(x);
  }
  else {
    integer_destroy(u);
    integer_destroy(v);
  }
  
  return 0;
}