/*-------------------------------------------------------------------------*/ 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); }
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; }
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; }
/** * 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; }
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; }
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 }
/* 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); } }