int hilb_comp::calc(int n_steps) // Possible return values: COMP_DONE, COMP_INTERRUPTED. { if (n_components == 0) return COMP_DONE; if (n_steps >= 0) { int calc_nsteps = nsteps + n_steps; while (calc_nsteps-- > 0) { int result = step(); if (result == COMP_DONE) return COMP_DONE; if (system_interrupted()) return COMP_INTERRUPTED; } return COMP_DONE_STEPS; } else for (;;) { int result = step(); if (result == COMP_DONE) return COMP_DONE; if (system_interrupted()) return COMP_INTERRUPTED; } }
enum ComputationStatusCode gb_emitter::calc_gb(int degree) { // This is when we ship off the elements in this degree. This should NEVER // be called if elements of lower degree have not been sent. if (this_degree != degree) { start_degree(degree); } for (;;) { if (system_interrupted()) return COMP_INTERRUPTED; if (n_i >= n_gens) return COMP_DONE; if (g != NULL) { ring_elem denom; gbvector *v = originalR->translate_gbvector_from_vec(gens->rows(), (*gens)[these[n_i]], denom); g->receive_generator(v, these[n_i], denom); } n_i++; n_left--; } }
void GaussElimComputation::start_computation() { if (status() == COMP_DONE) return; for (; row >= 0; row--) { if (gb_list[row] == NULL) continue; while (reduce_list[row] != NULL) { gm_elem *p = reduce_list[row]; reduce_list[row] = p->next; p->next = NULL; reduce(gb_list[row], p); // replaces p if (M2_gbTrace >= 3) { if (p->f == NULL) { if (p->fsyz == NULL) emit_wrapped("o"); else emit_wrapped("z"); } else emit_wrapped("r"); } else { } insert(p); n_pairs++; if (system_interrupted()) { set_status(COMP_INTERRUPTED); return; } if (n_pairs == stop_.pair_limit) { set_status(COMP_DONE_PAIR_LIMIT); return; } if (n_syz == stop_.syzygy_limit) { set_status(COMP_DONE_SYZYGY_LIMIT); return; } } } // Now auto reduce these for (int r = 1; r < gens->n_rows(); r++) { if (gb_list[r] == 0) continue; reduce(gb_list[r]->f, gb_list[r]->fsyz, true); } if (M2_gbTrace >= 1) { buffer o; text_out(o); emit(o.str()); } set_status(COMP_DONE); }
int PfaffianComputation::calc(int nsteps) { for (;;) { int result = step(); if (result == COMP_DONE) return COMP_DONE; if (--nsteps == 0) return COMP_DONE_STEPS; if (system_interrupted()) return COMP_INTERRUPTED; } }
int DetComputation::calc(int nsteps) { for (;;) { int r = step(); if (M2_gbTrace >= 3) emit_wrapped("."); if (r == COMP_DONE) return COMP_DONE; if (--nsteps == 0) return COMP_DONE_STEPS; if (system_interrupted()) return COMP_INTERRUPTED; } }
void binomialGB_comp::start_computation() { binomial_s_pair s; int *deg = 0; if (stop_.always_stop) return; // don't change status if (stop_.stop_after_degree) deg = &stop_.degree_limit->array[0]; while (Pairs->next(deg, s, top_degree)) { ComputationStatusCode ret = gb_done(); if (ret != COMP_COMPUTING) return; process_pair(s); // consumes 's'. if (system_interrupted()) { set_status(COMP_INTERRUPTED); return; } } if (Pairs->n_elems() == 0) set_status(COMP_DONE); else set_status(COMP_DONE_DEGREE_LIMIT); }
bool GF::initialize_GF(const RingElement *prim) { // set the GF ring tables. Returns false if there is an error. _primitive_element = prim; _originalR = prim->get_ring()->cast_to_PolynomialRing(); initialize_ring(_originalR->charac(), PolyRing::get_trivial_poly_ring()); declare_field(); int i,j; if (_originalR->n_quotients() != 1) { ERROR("rawGaloisField expected an element of a quotient ring of the form ZZ/p[x]/(f)"); return false; } ring_elem f = _originalR->quotient_element(0); Nterm *t = f; int n = _originalR->getMonoid()->primary_degree(t->monom); Q_ = P; for (i=1; i<n; i++) Q_ *= P; Qexp_ = n; Q1_ = Q_-1; _ZERO = 0; _ONE = Q1_; _MINUS_ONE = (P == 2 ? _ONE : Q1_/2); // Get ready to create the 'one_table' array<ring_elem> polys; polys.append(_originalR->from_int(0)); ring_elem primelem = prim->get_value(); polys.append(_originalR->copy(primelem)); ring_elem oneR = _originalR->one(); _x_exponent = -1; ring_elem x = _originalR->var(0); if (_originalR->is_equal(primelem, x)) _x_exponent = 1; for (i=2; i<Q_; i++) { ring_elem g = _originalR->mult(polys[i-1], primelem); polys.append(g); if (_originalR->is_equal(g, oneR)) break; if (_originalR->is_equal(g, x)) _x_exponent = i; } if (polys.length() != Q_) { ERROR("GF: primitive element expected"); return false; } assert(_x_exponent >= 0); // Set 'one_table'. _one_table = newarray_atomic(int,Q_); _one_table[0] = Q_-1; for (i=1; i<=Q_-1; i++) { if (system_interrupted()) return false; ring_elem f1 = _originalR->add(polys[i], oneR); for (j=1; j<=Q_-1; j++) if (_originalR->is_equal(f1, polys[j])) break; _one_table[i] = j; } // Create the Z/P ---> GF(Q) inclusion map _from_int_table = newarray_atomic(int,P); int a = _ONE; _from_int_table[0] = _ZERO; for (i=1; i<P; i++) { _from_int_table[i] = a; a = _one_table[a]; } zeroV = from_int(0); oneV = from_int(1); minus_oneV = from_int(-1); // M2::GaloisFieldTable G(*_originalR, primelem); // G.display(std::cout); return true; }
GaloisFieldTable::GaloisFieldTable(const PolynomialRing& R, const ring_elem prim): mCharac(static_cast<int>(R.characteristic())), mOriginalRing(R), mPrimitiveElement(prim) { M2_ASSERT(mOriginalRing.n_quotients() == 1); mGenerator = RingElement::make_raw(&R, R.copy(prim)); ring_elem f = mOriginalRing.quotient_element(0); Nterm *t = f; mDimension = mOriginalRing.getMonoid()->primary_degree(t->monom); mOrder = mCharac; for (int i=1; i<mDimension; i++) mOrder *= mCharac; mOne = mOrder - 1; // representation for the number 1: p^n - 1. mOrderMinusOne = mOne; // p^n - 1 mMinusOne = (mCharac == 2 ? mOne : mOne/2); // Get ready to create mOneTable. std::vector<ring_elem> polys; polys.push_back(mOriginalRing.from_long(0)); polys.push_back(mOriginalRing.copy(mPrimitiveElement)); ring_elem oneR = mOriginalRing.from_long(1); mGeneratorExponent = static_cast<GFElement>(-1); ring_elem x = mOriginalRing.var(0); if (mOriginalRing.is_equal(mPrimitiveElement, x)) mGeneratorExponent = 1; for (GFElement i=2; i<=mOne; i++) { ring_elem g = mOriginalRing.mult(polys[i-1], mPrimitiveElement); polys.push_back(g); if (mOriginalRing.is_equal(g, oneR)) break; if (mOriginalRing.is_equal(g, x)) mGeneratorExponent = i; } #if 0 for (size_t i = 0; i < polys.size(); i++) { std::cerr << i << " "; dringelem(&R, polys[i]); std::cerr << "\n"; } #endif M2_ASSERT(polys.size() == mOrder); M2_ASSERT(mGeneratorExponent != static_cast<GFElement>(-1)); // Set 'one_table'. mOneTable = newarray_atomic(GFElement,mOrder); mOneTable[0] = mOrderMinusOne; for (GFElement i=1; i<=mOrderMinusOne; i++) { if (system_interrupted()) { // first clean up? return; } ring_elem f1 = mOriginalRing.add(polys[i], oneR); GFElement j; for (j=0; j<=mOrderMinusOne; j++) if (mOriginalRing.is_equal(f1, polys[j])) break; if (j > mOrderMinusOne) { std::cout << "oops: didn't find element " << i << " !!" << std::endl; } mOneTable[i] = j; } // Create the ZZ/P ---> GF(Q) inclusion map mFromIntTable = newarray_atomic(GFElement,mCharac); GFElement a = mOne;; mFromIntTable[0] = 0; for (GFElement i=1; i<mCharac; i++) { mFromIntTable[i] = a; a = mOneTable[a]; } }
int LLLoperations::doLLL(MutableMatrix *A, MutableMatrix *Achange, MutableMatrix *LLLstate, int nsteps) { int n = A->n_cols(); if (n == 0) return COMP_DONE; // Extract the state from LLLstate: int k, kmax; ring_elem a, alphaTop, alphaBottom; buffer o; if (LLLstate->get_entry(0,n,a)) k = globalZZ->coerce_to_int(a); else k = 0; if (LLLstate->get_entry(0,n+1,a)) kmax = globalZZ->coerce_to_int(a); else kmax = 0; LLLstate->get_entry(0,n+2,alphaTop); // Don't free alphaTop! LLLstate->get_entry(0,n+3,alphaBottom); while (k < n && nsteps != 0 && !system_interrupted()) { if (M2_gbTrace >= 1) { o.reset(); o << "."; if (M2_gbTrace >= 2) o << k; if (nsteps % 20 == 0) o << newline; emit(o.str()); } nsteps--; if (k > kmax) { if (M2_gbTrace == 1) { o.reset(); o << "." << k; if (nsteps % 20 == 0) o << newline; emit(o.str()); } kmax = k; for (int j=0; j<=k; j++) { ring_elem u; A->dot_product(k,j,u); for (int i=0; i<=j-1; i++) { // u = (D#i * u - lambda#(k,i) * lambda#(j,i)) // D#(i-1) ring_elem Di, mki, mji, Di1; LLLstate->get_entry(i,i,Di); globalZZ->mult_to(u, Di); if (LLLstate->get_entry(i,k,mki) && LLLstate->get_entry(i,j,mji)) { ring_elem t1 = globalZZ->mult(mki,mji); globalZZ->subtract_to(u,t1); } if (i > 0) { LLLstate->get_entry(i-1,i-1,Di1); // Cannot be zero!! ring_elem t1 = globalZZ->divide(u,Di1); globalZZ->remove(u); u = t1; } } // At this point we have our element: LLLstate->set_entry(j,k,u); if (j == k && globalZZ->is_zero(u)) { ERROR("LLL vectors not independent"); return COMP_ERROR; } } } // end of the k>kmax initialization REDI(k,k-1,A,Achange,LLLstate); if (Lovasz(LLLstate,k,alphaTop,alphaBottom)) { SWAPI(k,kmax,A,Achange,LLLstate); k--; if (k == 0) k = 1; } else { for (int ell=k-2; ell>=0; ell--) REDI(k,ell,A,Achange,LLLstate); k++; } } // Before returning, reset k,kmax: LLLstate->set_entry(0,n,globalZZ->from_int(k)); LLLstate->set_entry(0,n+1,globalZZ->from_int(kmax)); if (k >= n) return COMP_DONE; if (nsteps == 0) return COMP_DONE_STEPS; return COMP_INTERRUPTED; }
// new code void gbB::do_computation() { ComputationStatusCode ret; spair *p; // initial state is STATE_NEWDEGREE if (stop_.always_stop) return; // don't change status if ((ret = computation_is_complete()) != COMP_COMPUTING) { set_status(ret); return; } if (M2_gbTrace == 15) { emit_line("[gb]"); } else if (M2_gbTrace >= 1) { emit_wrapped("[gb]"); } for (;;) { if (stop_.stop_after_degree && this_degree > stop_.degree_limit->array[0]) { // Break out now if we don't have anything else to compute in this degree. set_status(COMP_DONE_DEGREE_LIMIT); return; } if (M2_gbTrace & PrintingDegree) { } switch(state) { case STATE_NEWPAIRS: // Loop through all of the new GB elements, and // compute spairs. Start at np_i // np_i is initialized at the beginning, and also here. while (np_i < n_gb) { if (system_interrupted()) { set_status(COMP_INTERRUPTED); return; } if (gb[np_i]->minlevel & ELEMB_MINGB) update_pairs(np_i); np_i++; } state = STATE_NEWDEGREE; case STATE_NEWDEGREE: // Get the spairs and generators for the next degree if (S->n_in_degree == 0) { int old_degree = this_degree; npairs = spair_set_prepare_next_degree(this_degree); // sets this_degree if (old_degree < this_degree) first_in_degree = INTSIZE(gb); complete_thru_this_degree = this_degree-1; if (npairs == 0) { state = STATE_DONE; set_status(COMP_DONE); return; } if (stop_.stop_after_degree && this_degree > stop_.degree_limit->array[0]) { set_status(COMP_DONE_DEGREE_LIMIT); return; } if (hilbert) { if (!hilbert->setDegree(this_degree)) { if (error()) set_status(COMP_ERROR); else set_status(COMP_INTERRUPTED); return; } } } if (M2_gbTrace == 15) { buffer o; o << "DEGREE " << this_degree; o << ", number of spairs = " << npairs; if (hilbert) o << ", expected number in this degree = " << hilbert->nRemainingExpected(); emit_line(o.str()); } else if (M2_gbTrace >= 1) { buffer o; o << '{' << this_degree << '}'; o << '('; if (hilbert) o << hilbert->nRemainingExpected() << ','; o << npairs << ')'; emit_wrapped(o.str()); } ar_i = n_gb; ar_j = ar_i+1; state = STATE_SPAIRS; case STATE_SPAIRS: case STATE_GENS: // Compute the spairs for this degree while ((p = spair_set_next()) != 0) { process_spair(p); npairs--; n_pairs_computed++; if ((ret = computation_is_complete()) != COMP_COMPUTING) { set_status(ret); return; } if (system_interrupted()) { set_status(COMP_INTERRUPTED); return; } } state = STATE_AUTOREDUCE; // or state = STATE_NEWPAIRS case STATE_AUTOREDUCE: // This is still possibly best performed when inserting a new element // Perform the necessary or desired auto-reductions while (ar_i < n_gb) { while (ar_j < n_gb) { if (system_interrupted()) { set_status(COMP_INTERRUPTED); return; } R->gbvector_auto_reduce(F, Fsyz, gb[ar_i]->g.f, gb[ar_i]->g.fsyz, gb[ar_j]->g.f, gb[ar_j]->g.fsyz); ar_j++; } ar_i++; ar_j = ar_i+1; } state = STATE_NEWPAIRS; break; case STATE_DONE: return; } } }
enum ComputationStatusCode F4GB::start_computation(StopConditions &stop_) { clock_sort_columns = 0; clock_gauss = 0; clock_make_matrix = 0; int npairs; // test_spair_code(); enum ComputationStatusCode is_done = COMP_COMPUTING; reset_master_syz(); for (;;) { if (system_interrupted()) { is_done = COMP_INTERRUPTED; break; } is_done = computation_is_complete(stop_); if (is_done != COMP_COMPUTING) break; this_degree = S->prepare_next_degree(-1, npairs); if (npairs == 0) { is_done = COMP_DONE; break; } if (stop_.stop_after_degree && this_degree > stop_.degree_limit->array[0]) { is_done = COMP_DONE_DEGREE_LIMIT; break; } if (hilbert) { if (!hilbert->setDegree(this_degree)) { if (error()) is_done = COMP_ERROR; else is_done = COMP_INTERRUPTED; break; } } if (M2_gbTrace >= 1) { if (hilbert) fprintf(stderr, "DEGREE %d (nexpected %d npairs %d)\n", this_degree, hilbert->nRemainingExpected(), npairs); else fprintf(stderr, "DEGREE %d (npairs %d)\n", this_degree, npairs); } do_spairs(); complete_thru_this_degree = this_degree; } clear_master_syz(); if (M2_gbTrace>=2) { fprintf(stderr, "number of calls to cancel row : %ld\n", KK->n_dense_row_cancel); fprintf(stderr, "number of calls to subtract_multiple: %ld\n", KK->n_subtract_multiple); fprintf(stderr, "total time for sorting columns: %f\n", clock_sort_columns); if (using_syz) fprintf(stderr, "total time for sorting syz columns: %f\n", syz_clock_sort_columns); fprintf(stderr, "total time for making matrix (includes sort): %f\n", ((double)clock_make_matrix)/CLOCKS_PER_SEC); fprintf(stderr, "total time for gauss: %f\n", ((double)clock_gauss)/CLOCKS_PER_SEC); fprintf(stderr, "number of spairs computed : %ld\n", n_pairs_computed); fprintf(stderr, "number of reduction steps : %ld\n", n_reduction_steps); } fprintf(stderr, "number of spairs removed by criterion = %ld\n", S->n_unneeded_pairs()); M->show(); return is_done; }