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); }
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"); insert(p); n_pairs++; if (test_Field(THREADLOCAL(interrupts_interruptedFlag,struct atomic_field))) { 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; } } }
bool gbB::process_spair(spair *p) { stats_npairs++; bool not_deferred = reduceit(p); if (!not_deferred) return true; gbelem_type minlevel = (p->type == SPAIR_GEN ? ELEMB_MINGEN : 0) | ELEMB_MINGB; if (p->type == SPAIR_GEN) n_gens_left--; POLY f = p->x.f; p->x.f.f = 0; p->x.f.fsyz = 0; spair_delete(p); if (!R->gbvector_is_zero(f.f)) { insert_gb(f,minlevel); if (M2_gbTrace == 3) emit_wrapped("m"); } else { originalR->get_quotient_info()->gbvector_normal_form(Fsyz, f.fsyz); if (!R->gbvector_is_zero(f.fsyz)) { /* This is a syzygy */ collect_syzygy(f.fsyz); if (M2_gbTrace == 3) emit_wrapped("z"); } else { if (M2_gbTrace == 3) emit_wrapped("o"); } } return true; }
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 gbB::spair_set_defer(spair *&p) // Defer the spair p until later in this same degree // The spair should have been reduced a number of times // already, so its type should be SPAIR_GEN or SPAIR_ELEM { if (M2_gbTrace == 15) { emit_line(" deferred by reduction count"); } else if (M2_gbTrace >= 4) emit_wrapped("D"); // spair_delete(p); // ONLY FOR TESTING!! THIS IS INCORRECT!! // return; S->n_in_degree++; if (p->type == SPAIR_GEN) { S->gen_last_deferred->next = p; S->gen_last_deferred = p; } else { S->spair_last_deferred->next = p; S->spair_last_deferred = p; } }
// 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; } } }
void gbB::remainder(POLY &f, int degf, bool use_denom, ring_elem &denom) // find the remainder of f = [g,gsyz] wrt the GB, // i.e. replace f with h[h,hsyz], st // h = f - sum(a_i * g_i), in(f) not in in(G) // hsyz = fsyz - sum(a_i * gsyz_i) // denom is unchanged // (Here: G = (g_i) is the GB, and a_i are polynomials generated // during division). // c is an integer, and is returned as 'denom'. // Five issues: // (a) if gcd(c, coeffs(f)) becomes > 1, can we divide // c, f, by this gcd? If so, how often do we do this? // (b) do we reduce by any element of the GB, or only those whose // sugar degree is no greater than degf? // (c) can we exclude an element of the GB from the g_i? // (for use in auto reduction). // (d) can we reduce by the minimal GB instead of the original GB? // ANSWER: NO. Instead, use a routine to make a new GB. // (e) Special handling of quotient rings: none needed. { exponents EXP = ALLOCATE_EXPONENTS(exp_size); gbvector head; gbvector *frem = &head; frem->next = 0; int count = 0; POLY h = f; while (!R->gbvector_is_zero(h.f)) { int gap; R->gbvector_get_lead_exponents(F, h.f, EXP); int x = h.f->comp; int w = find_good_divisor(EXP,x,degf, gap); // replaced gap, g. if (w < 0 || gap > 0) { frem->next = h.f; frem = frem->next; h.f = h.f->next; frem->next = 0; } else { POLY g = gb[w]->g; R->gbvector_reduce_lead_term(F, Fsyz, head.next, h.f, h.fsyz, g.f, g.fsyz, use_denom, denom); count++; // stats_ntail++; if (M2_gbTrace >= 10) { buffer o; o << " tail reducing by "; R->gbvector_text_out(o,F,g.f, 2); o << "\n giving "; R->gbvector_text_out(o,F,h.f, 3); emit_line(o.str()); } } } h.f = head.next; R->gbvector_remove_content(h.f, h.fsyz, use_denom, denom); f.f = h.f; f.fsyz = h.fsyz; if ((M2_gbTrace & PRINT_SPAIR_TRACKING) != 0) { buffer o; o << "number of reduction steps was " << count; emit_line(o.str()); } else if (M2_gbTrace >= 4 && M2_gbTrace != 15) { buffer o; o << "," << count; emit_wrapped(o.str()); } }
bool gbB::reduceit(spair *p) { /* Returns false iff we defer computing this spair. */ /* If false is returned, this routine has grabbed the spair 'p'. */ exponents EXP = ALLOCATE_EXPONENTS(exp_size); int tmf, wt; int count = -1; if (M2_gbTrace == 15) { buffer o; o << "considering "; spair_text_out(o,p); o << " : "; emit_line(o.str()); } compute_s_pair(p); /* Changes the type, possibly */ while (!R->gbvector_is_zero(p->f())) { if (count++ > max_reduction_count) { spair_set_defer(p); return false; } if (M2_gbTrace >= 5) { if ((wt = weightInfo->gbvector_weight(p->f(), tmf)) > this_degree) { buffer o; o << "ERROR: degree of polynomial is too high: deg " << wt << " termwt " << tmf << " expectedeg " << this_degree << newline; emit(o.str()); } } int gap,w; R->gbvector_get_lead_exponents(F, p->f(), EXP); int x = p->f()->comp; w = find_good_divisor(EXP,x,this_degree, gap); // replaced gap, g. if (w < 0) break; if (false && gap > 0) { POLY h; h.f = R->gbvector_copy(p->x.f.f); h.fsyz = R->gbvector_copy(p->x.f.fsyz); insert_gb(h,(p->type == SPAIR_GEN ? ELEMB_MINGEN : 0)); } POLY g = gb[w]->g; R->gbvector_reduce_lead_term(F, Fsyz, 0, p->f(), p->fsyz(), /* modifies these */ g.f, g.fsyz); stats_nreductions++; if (M2_gbTrace == 15) { buffer o; o << " reducing by g" << w; o << ", yielding "; R->gbvector_text_out(o, F, p->f(), 3); emit_line(o.str()); } if (R->gbvector_is_zero(p->f())) break; if (gap > 0) { p->deg += gap; if (M2_gbTrace == 15) { buffer o; o << " deferring to degree " << p->deg; emit_line(o.str()); } spair_set_insert(p); return false; } } if (M2_gbTrace >= 4 && M2_gbTrace != 15) { buffer o; o << "." << count; emit_wrapped(o.str()); } return true; }
inline void emit_wrapped(int prlevel, const char *s) { if (M2_gbTrace >= prlevel) emit_wrapped(s); }