Exemplo n.º 1
0
/*-------------------------------------------------------------------------*/
void
poly_rootopt_run(poly_rootopt_t *data, mpz_t * alg_coeffs, 
		mpz_t * rat_coeffs, double sizeopt_norm, 
		double projective_alpha)
{
	uint32 i;
	stage2_curr_data_t *s = (stage2_curr_data_t *)(data->internal);
	curr_poly_t *c = &s->curr_poly;
	dd_precision_t precision = 0;
	uint32 precision_changed = 0;

	if (!dd_precision_is_ieee()) {
		precision_changed = 1;
		precision = dd_set_precision_ieee();
	}

	mpz_set(c->gmp_lina[0], rat_coeffs[0]);
	mpz_set(c->gmp_lina[1], rat_coeffs[1]);
	mpz_neg(c->gmp_d, rat_coeffs[0]);
	mpz_set(c->gmp_p, rat_coeffs[1]);

	for (i = 0; i <= data->degree; i++)
		mpz_set(c->gmp_a[i], alg_coeffs[i]);

	if (sizeopt_norm == 0) {

		/* size optimization possibly did not run
		   previously; check poly and get the norm */

		if (check_poly(c, c->gmp_a, c->gmp_lina[0], 
				data->gmp_N, data->degree) != 1) {
			goto finished;
		}

		optimize_initial(c, data->degree, &sizeopt_norm, 1);

		stage2_root_score(data->degree, c->gmp_a, 100, 
				&projective_alpha, 1);
	}

	if (sizeopt_norm * exp(projective_alpha) <= data->max_sizeopt_norm)
		root_sieve_run(data, sizeopt_norm, projective_alpha);

finished:
	if (precision_changed)
		dd_clear_precision(precision);
}
Exemplo n.º 2
0
bool SchreyerFrame::debugCheckOrder(int lev) const
{
  if (lev == 0) return true;
  bool result = true;
  auto& mylevel = level(lev);
  auto& myorder = schreyerOrder(lev-1);
  int which = 0;
  for (auto i = mylevel.cbegin(); i != mylevel.cend(); ++i, ++which)
    {
      if (!check_poly(ring(), i->mSyzygy, myorder))
        {
          std::cout << "Error: terms of polynomial at level " << lev << " location " << which << " not in order" << std::endl;
          std::cout << "  poly = ";
          display_poly(stdin, ring(), i->mSyzygy);
          std::cout << std::endl;
          result = false;
        }
    }
  return result;
}
Exemplo n.º 3
0
bool SchreyerFrame::insertLevelOne(res_packed_monomial monom, int deg, poly& syzygy)
{
  insertBasic(1, monom, deg); // deg is the actual degree of this element.
  long comp = monoid().get_component(monom);
  auto last = level(1).size();
  auto& p = level(0)[comp];
  if (p.mBegin == -1)
    p.mBegin = last-1;
  p.mEnd = last;
  if (!check_poly(ring(), syzygy, schreyerOrder(0)))
    {
      if (M2_gbTrace >= 1)
        {
          std::cout << "Error: expected terms of polynomial to be in order, in poly#" << last << ": ";
          display_poly(stdout, ring(), syzygy);
          std::cout << std::endl;
        }
      return false;
    }
  std::swap(level(1)[level(1).size()-1].mSyzygy, syzygy);
  return true;
}
Exemplo n.º 4
0
/**
 * Run step 5 of the AKS algorithm.
 */
int check_polys(mpz_t r, mpz_t n) {
  mpz_t a, lim;
  mpz_init(a);
  mpz_init(lim);

  int status = PRIME;
  if (aks_debug) gmp_printf("computing upper limit\n");
  compute_upper_limit(lim, r, n);
  if (aks_debug) gmp_printf("lim=%Zd\n", lim);
  // For values of a from 1 to sqrt(totient(r)) * log(n)
  for (mpz_set_ui(a, 1); mpz_cmp(a, lim) <= 0; mpz_add_ui(a, a, 1)) {
    if (!check_poly(n, a, r)) {
      status = COMPOSITE;
      break;
    }
  }

  mpz_clear(a);
  mpz_clear(lim);

  return status;
}
Exemplo n.º 5
0
static int
pol_expand(curr_poly_t *c, mpz_t gmp_N, mpz_t high_coeff,
		mpz_t gmp_p, mpz_t gmp_d, 
		double coeff_bound, uint32 degree)
{
	uint32 i, j;

	if (mpz_cmp_ui(c->gmp_p, (mp_limb_t)1) == 0)
		mpz_set_ui(c->gmp_help1, (mp_limb_t)1);
	else {
		if (!mpz_invert(c->gmp_help1, gmp_d, gmp_p))
			return 0;
	}

	mpz_set(c->gmp_b[1], c->gmp_help1);
	for (i = 2; i < degree; i++)
		mpz_mul(c->gmp_b[i], c->gmp_b[i-1], c->gmp_help1);

	mpz_set(c->gmp_c[1], gmp_d);
	for (i = 2; i <= degree; i++)
		mpz_mul(c->gmp_c[i], c->gmp_c[i-1], gmp_d);

	mpz_set(c->gmp_a[degree], high_coeff);
	mpz_set(c->gmp_help2, gmp_N);

	for (i = degree - 1; (int32)i >= 0; i--) {

		mpz_mul(c->gmp_help3, c->gmp_a[i+1], c->gmp_c[i+1]);
		mpz_sub(c->gmp_help3, c->gmp_help2, c->gmp_help3);
		mpz_tdiv_q(c->gmp_help2, c->gmp_help3, gmp_p);

		if (i > 0) {
			mpz_tdiv_q(c->gmp_a[i], c->gmp_help2, c->gmp_c[i]);
			mpz_mul(c->gmp_help3, c->gmp_help2, c->gmp_b[i]);
			mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_a[i]);
			mpz_tdiv_r(c->gmp_help4, c->gmp_help3, gmp_p);

			if (mpz_sgn(c->gmp_help4) < 0)
				mpz_add(c->gmp_help4, c->gmp_help4, gmp_p);

			mpz_add(c->gmp_a[i], c->gmp_a[i], c->gmp_help4);
		}
	}
	mpz_set(c->gmp_a[0], c->gmp_help2);

	mpz_tdiv_q_2exp(c->gmp_help1, gmp_d, (mp_limb_t)1);
	for (i = 0; i < degree; i++) {
		for (j = 0; j < MAX_CORRECT_STEPS &&
			    mpz_cmpabs(c->gmp_a[i], c->gmp_help1) > 0; j++) {

			if (mpz_sgn(c->gmp_a[i]) < 0) {
				mpz_add(c->gmp_a[i], c->gmp_a[i], gmp_d);
				mpz_sub(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p);
			}
			else {
				mpz_sub(c->gmp_a[i], c->gmp_a[i], gmp_d);
				mpz_add(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p);
			}
		}

		if (j == MAX_CORRECT_STEPS)
			return 0;
	}

#if 0
	gmp_printf("%+Zd\n", c->gmp_lina[0]);
	gmp_printf("%+Zd\n", c->gmp_lina[1]);
	for (i = 0; i <= degree; i++)
		gmp_printf("%+Zd\n", c->gmp_a[i]);

	printf("coeff ratio = %.5lf\n",
		fabs(mpz_get_d(c->gmp_a[degree-2])) / coeff_bound);
#endif

	if (check_poly(c, c->gmp_a, 
			c->gmp_lina[0], gmp_N, degree) != 1) {
		return 0;
	}

	if (mpz_cmpabs_d(c->gmp_a[degree - 2], coeff_bound) > 0) {
		return 1;
	}
	return 2;
}
Exemplo n.º 6
0
static void BSPTreeCreateRecursive(BSPTreeNode *tree,
				   PolyListNode *pllist,
#if BSPTREE_STATS
				   int depth,
#endif
				   struct obstack *scratch)
{
  PolyListNode *plnode, *front, *back;
  EdgeIntersection edges[2];

  tree->front = tree->back = NULL;
  ListPop(pllist, plnode);
  tree->polylist = plnode;
  check_poly(plnode->poly);
  PolyPlane(plnode, &tree->plane);

  front = back = NULL;
  while (pllist) {    
    ListPop(pllist, plnode);
    check_poly(plnode->poly);
    switch (ClassifyPoly(&tree->plane, plnode->poly, edges)) {
    case BACKOF:
      check_poly(plnode->poly);
      ListPush(back, plnode);
      break;
    case COPLANAR:
      check_poly(plnode->poly);
      ListPush(tree->polylist, plnode);
      break;
    case INFRONTOF:
      check_poly(plnode->poly);
      ListPush(front, plnode);
      break;
    case BOTH_SIDES:
      check_poly(plnode->poly);
      SplitPolyNode(plnode, &front, &back, edges, scratch);
      break;
    }
  }
  if (front) {
    tree->front = obstack_alloc(scratch, sizeof(*tree->front));
    BSPTreeCreateRecursive(tree->front, front,
#if BSPTREE_STATS
			   depth+1,
#endif
			   scratch);
  }
  if (back) {
    tree->back = obstack_alloc(scratch, sizeof(*tree->back));
    BSPTreeCreateRecursive(tree->back, back,
#if BSPTREE_STATS
			   depth+1,
#endif
			   scratch);
  }
#if BSPTREE_STATS
  if (depth > tree_depth) {
    tree_depth = depth;
  }
#endif
}
Exemplo n.º 7
0
/* Split plnode along plane. We know that plane really intersects
 * plnode->poly. We also know that plnode->poly is planar and convex.
 *
 * Given this assumptions we know that plnode->poly has to be split
 * into exactly two pieces. 
 */
static inline void SplitPolyNode(PolyListNode *plnode,
				 PolyListNode **front, PolyListNode **back,
				 EdgeIntersection edges[2],
				 struct obstack *scratch)
{
  const void **tagged_app = plnode->tagged_app;
  Poly *poly = plnode->poly, savedp;
  VARARRAY(savedv, Vertex *, poly->n_vertices);
  Vertex *v0, *v1, **vpos;
  int istart[2], iend[2], i, nv[2];
  Vertex *vstart[2], *vend[2];

#if BSPTREE_STATS
  ++n_tree_polys;
#endif

  vstart[0] = vstart[1] = vend[0] = vend[1] = NULL;
  istart[0] = istart[1] = iend[0] = iend[1] = -1;

  /* first point of intersection */
  if (fzero(edges[0].scp[0])) {
    v0 = poly->v[edges[0].v[0]];
    if (fpos(edges[0].scp[1])) {
      istart[0] = edges[0].v[0];
      iend[1]   = edges[0].v[0];
    } else {
      istart[1] = edges[0].v[0];
      iend[0]   = edges[0].v[0]; 
    }
  } else if (fzero(edges[0].scp[1])) {
    v0 = poly->v[edges[0].v[1]];
    if (fpos(edges[0].scp[0])) {
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[1];
    } else {
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[0].v[0]];
    Vertex *V1 = poly->v[edges[0].v[1]];
    
    v0 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[0].scp[1]/(edges[0].scp[1]-edges[0].scp[0]);
#if 0
    mu1 = edges[0].scp[0]/(edges[0].scp[0]-edges[0].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    /* Use denormalized variant; otherwise textures may come out wrong
     * because the homogeneous divisor is used for perspective
     * corrections.
     */
    if (poly->flags & VERT_ST) {
      v0->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v0->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } 
    if (!finite(v0->pt.x + v0->pt.y + v0->pt.z)){
      abort();
    }
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v0->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      /* The averaged vertex normals do not have an orientation, so
       * try to orient them w.r.t. the polygon normal before computing
       * the linear combination.
       */
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      }
      Pt3Unit(&v0->vn);
    }

    if (fpos(edges[0].scp[0])) {
      vstart[1] = vend[0] = v0;
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[0];
    } else {
      vstart[0] = vend[1] = v0;
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[0];
    }
  }

  /* second point of intersection */
  if (fzero(edges[1].scp[0])) {
    v1 = poly->v[edges[1].v[0]];
    if (fpos(edges[1].scp[1])) {
      istart[0] = edges[1].v[0];
      iend[1]   = edges[1].v[0];
    } else {
      istart[1] = edges[1].v[0];
      iend[0]   = edges[1].v[0]; 
    }
  } else if (fzero(edges[1].scp[1])) {
    v1 = poly->v[edges[1].v[1]];
    if (fpos(edges[1].scp[0])) {
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[1];
    } else {
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[1].v[0]];
    Vertex *V1 = poly->v[edges[1].v[1]];
    
    v1 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[1].scp[1]/(edges[1].scp[1]-edges[1].scp[0]);
#if 0
    mu1 = edges[1].scp[0]/(edges[1].scp[0]-edges[1].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    if (poly->flags & VERT_ST) {
      v1->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v1->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    }
    if (!finite(v1->pt.x + v1->pt.y + v1->pt.z))
      abort();
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v1->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      }
      Pt3Unit(&v1->vn);
    }

    if (fpos(edges[1].scp[0])) {
      vstart[1] = vend[0] = v1;
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[0];
    } else {
      vstart[0] = vend[1] = v1;
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[0];
    }
  }

  ListPush(*front, plnode);
  ListPush(*back, new_poly_list_node(tagged_app, scratch));

  if ((poly->flags & POLY_NONFLAT)) {
    if (!(*front)->pn) {
      /* Compute the normal on the parent element to avoid numerical
       * instabilities on increasingly degenerated polygons.
       */
      (*front)->pn = obstack_alloc(scratch, sizeof(Point3));
      PolyNormal(poly, (*front)->pn,
		 true /* 4d */, false /* evert */, NULL, NULL);
    }
    (*back)->pn = (*front)->pn;
  }

  for (i = 0; i < 2; i++) {
    nv[i] = iend[i] - istart[i] + 1;
    if (nv[i] < 0) {
      nv[i] += poly->n_vertices;
    }
    nv[i] += (vstart[i] != NULL) + (vend[i] != NULL);
  }

  if (poly->flags & POLY_SCRATCH) {

    savedp = *poly;
    memcpy(savedv, poly->v, poly->n_vertices*sizeof(Vertex *));

    if (nv[0] <= poly->n_vertices) {
      poly->n_vertices = nv[0];
      (*front)->poly = poly;
      (*back)->poly  = new_poly(nv[1], NULL, scratch);
    } else {
      if (nv[1] > poly->n_vertices) {
	abort();
      }
      poly->n_vertices = nv[1];
      (*back)->poly = poly;
      (*front)->poly  = new_poly(nv[0], NULL, scratch);
    }
    
    /* Attention: gcc had problems with this code snippet with
     * -fstrict-aliasing, the "#if 1" stuff seems to work. In the
     * "#else" version gcc somehow lost the "savedp.v = savedv"
     * assignment. I think this is a compiler bug.
     */
    poly = &savedp;
#if 1
    poly->v = savedv;
#else
    savedp.v = savedv;
#endif
  } else {
    (*front)->poly  = new_poly(nv[0], NULL, scratch);
    (*back)->poly  = new_poly(nv[1], NULL, scratch);
  }

  for (i = 0; i < 2; i++) {
    PolyListNode *half = (i == 0) ? *front : *back;
    int j;

    vpos = half->poly->v;
    if (vstart[i] != NULL) {
      *vpos++ = vstart[i];
    }
    if (istart[i] <= iend[i]) {
      for (j = istart[i]; j <= iend[i] && j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
    } else {
      for (j = istart[i]; j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
      for (j = 0; j <= iend[i]; j++) {
	*vpos++ = poly->v[j];
      }
    }
    if (vend[i] != NULL) {
      *vpos++ = vend[i];
    }
    half->poly->pcol  = poly->pcol;
    half->poly->pn    = poly->pn;
    half->poly->flags = poly->flags|POLY_SCRATCH;

    check_poly(half->poly);
  }
}