void F4GB::reorder_rows() { //??? reorder rows in <mat> and <syz> simultaneously? int nrows = INTSIZE(mat->rows); int ncols = INTSIZE(mat->columns); coefficient_matrix::row_array newrows; VECTOR(long) rowlocs; // 0..nrows-1 of where row as been placed newrows.reserve(nrows); rowlocs.reserve(nrows); for (int r = 0; r < nrows; r++) rowlocs.push_back(-1); for (int c = 0; c < ncols; c++) { int oldrow = mat->columns[c].head; if (oldrow >= 0) { // Move the row into place int newrow = INTSIZE(newrows); newrows.push_back(mat->rows[oldrow]); rowlocs[oldrow] = newrow; mat->columns[c].head = newrow; if (mat->columns[c].head == oldrow) mat->columns[c].head = newrow; } } for (int r = 0; r < nrows; r++) if (rowlocs[r] < 0) newrows.push_back(mat->rows[r]); std::swap(mat->rows, newrows); }
void F4GB::new_GB_elements() { /* After LU decomposition, loop through each row of the matrix. If the corresponding lead term is not in the initial ideal (or, at least, wasn't) then insert GB element (and so update spairs, etc, but don't do auto_reduce...) If instead the lead term is not new, then keep track of this information somehow: place ... into a monheap... */ /* If we can place the possible new elements first, or in a separate place, then we don't need to loop through all of these */ for (int r=0; r<mat->rows.size(); r++) { if (is_new_GB_row(r)) { insert_syz(syz->rows[r], INTSIZE(gb)); insert_gb_element(mat->rows[r]); } else { insert_syz(syz->rows[r]); } } }
void F4GB::process_column(int c) { /* If this column has been handled before, return. Otherwise, find a GB element whose lead term divides this monomial, and either mark this colum as not an initial element, OR append a row */ column_elem &ce = mat->columns[c]; if (ce.head >= -1) return; int32_t which; bool found = lookup->find_one_divisor_packed(M, ce.monom, which); if (found) { packed_monomial n = next_monom; M->unchecked_divide(ce.monom, gb[which]->f.monoms, n); B.intern(1+M->monomial_size(n)); next_monom = B.reserve(1+M->max_monomial_size()); next_monom++; //M->set_component(which, n); ce.head = INTSIZE(mat->rows); load_row(n,which); } else ce.head = -1; }
FreeModule *FreeModule::make_schreyer(const GBMatrix *m) { const FreeModule *F = m->get_free_module(); const PolynomialRing *R = F->get_ring()->cast_to_PolynomialRing(); if (R == 0) { ERROR("expected a polynomial ring"); return nullptr; } FreeModule *G = R->make_FreeModule(); int rk = INTSIZE(m->elems); if (rk == 0) return G; for (int i=0; i<rk; i++) { int *deg = R->degree_monoid()->make_one(); gbvector * v = m->elems[i]; if (v != 0) R->get_gb_ring()->gbvector_multidegree(F, v, deg); G->append(deg); } G->schreyer = SchreyerOrder::create(m); return G; }
/* Sorting a list of spairs */ void gbB::spairs_sort(int len, spair *&ps) { if (ps == 0 || ps->next == 0) return; if (len <= 1) return; spairs a; // array of spair's spairs b; // these are the ones which are uncomputed, but whose lead_of_spoly is 0. a.reserve(len); for (spair *p = ps; p != 0; p=p->next) { if ((p->type > gbB::SPAIR_SKEW) || p->lead_of_spoly) a.push_back(p); else b.push_back(p); } SPolySorterB SP(R,F); QuickSorter<SPolySorterB>::sort(&SP,&a[0],a.size()); int asize = INTSIZE(a); int bsize = INTSIZE(b); if (asize > 0) { ps = a[0]; for (int i=1; i<asize; i++) a[i-1]->next = a[i]; } else if (bsize > 0) { ps = b[0]; //debugging// fprintf(stderr, "bsize is %d\n",bsize); } else { ps = 0; return; } if (asize > 0) a[asize-1]->next = (bsize > 0 ? b[0] : 0); if (bsize > 0) { for (int i=1; i<bsize; i++) b[i-1]->next = b[i]; b[bsize-1]->next = 0; } }
void F4GB::insert_gb_element(row_elem &r) { // Insert row as gb element. // Actions to do: // translate row to a gbelem + poly // set degrees as needed // insert the monomial into the lookup table // find new pairs associated to this new element int nslots = M->max_monomial_size(); int nlongs = r.len * nslots; gbelem *result = new gbelem; result->f.len = r.len; // If the coeff array is null, then that means the coeffs come from the original array // Here we copy it over. result->f.coeffs = (r.coeffs ? r.coeffs : KK->copy_F4CoefficientArray(r.len, get_coeffs_array(r))); r.coeffs = 0;; result->f.monoms = Mem->allocate_monomial_array(nlongs); monomial_word *nextmonom = result->f.monoms; for (int i=0; i<r.len; i++) { M->copy(mat->columns[r.comps[i]].monom, nextmonom); nextmonom += nslots; } Mem->components.deallocate(r.comps); r.len = 0; result->deg = this_degree; result->alpha = static_cast<int>(M->last_exponent(result->f.monoms)); result->minlevel = ELEM_MIN_GB; // MES: How do // we distinguish between ELEM_MIN_GB, ELEM_POSSIBLE_MINGEN? int which = INTSIZE(gb); gb.push_back(result); if (hilbert) { int x; int *exp = newarray_atomic(int, M->n_vars()); M->to_intstar_vector(result->f.monoms, exp, x); hilbert->addMonomial(exp, x+1); deletearray(exp); } // now insert the lead monomial into the lookup table varpower_monomial vp = newarray_atomic(varpower_word, 2 * M->n_vars() + 1); M->to_varpower_monomial(result->f.monoms, vp); lookup->insert_minimal_vp(M->get_component(result->f.monoms), vp, which); deleteitem(vp); // now go forth and find those new pairs S->find_new_pairs(is_ideal); }
/////////////////////////////////////////////////// // Creation of the matrix over K ////////////////// /////////////////////////////////////////////////// int F4GB::new_column(packed_monomial m) { // m is a packed monomial, unique via the hash table H, B. column_elem c; int next_column = INTSIZE(mat->columns); m[-1] = next_column; c.monom = m; c.head = -2; mat->columns.push_back(c); return next_column; }
SchreyerOrder *SchreyerOrder::create(const GBMatrix *m) { #ifdef DEVELOPMENT #warning "the logic in SchreyerOrder creation is WRONG!" #endif int i; const FreeModule *F = m->get_free_module(); const Ring *R = F->get_ring(); const SchreyerOrder *S = F->get_schreyer_order(); const PolynomialRing *P = R->cast_to_PolynomialRing(); const Monoid *M = P->getMonoid(); SchreyerOrder *result = new SchreyerOrder(M); int rk = INTSIZE(m->elems); if (rk == 0) return result; int *base = M->make_one(); int *tiebreaks = newarray_atomic(int,rk); int *ties = newarray_atomic(int,rk); for (i=0; i<rk; i++) { gbvector *v = m->elems[i]; if (v == NULL || S == NULL) tiebreaks[i] = i; else tiebreaks[i] = i + rk * S->compare_num(v->comp-1); } // Now sort tiebreaks in increasing order. std::sort<int *>(tiebreaks, tiebreaks+rk); for (i=0; i<rk; i++) ties[tiebreaks[i] % rk] = i; for (i=0; i<rk; i++) { gbvector *v = m->elems[i]; if (v == NULL) M->one(base); else //if (S == NULL) M->copy(v->monom, base); #ifdef DEVELOPMENT #warning "Schreyer unencoded case not handled here" #endif #if 0 // else // M->mult(v->monom, S->base_monom(i), base); #endif result->append(ties[i], base); } intern_SchreyerOrder(result); M->remove(base); deletearray(tiebreaks); deletearray(ties); return result; }
void F4GB::gauss_reduce_linbox() // dumps the current matrix into a file in the linbox sparse matrix format { // dump the matrix in a file char fname[30]; sprintf(fname, "tmp.%i.matrix", this_degree); FILE* mfile = fopen(fname, "w"); int nrows = INTSIZE(mat->rows); int ncols = INTSIZE(mat->columns); fprintf(mfile, "%i %i M\n", nrows, ncols); for (int i=0; i<nrows; i++) { row_elem &r = mat->rows[i]; int *sparseelems = static_cast<int *>(r.coeffs); for (int j=0; j<r.len; j++) { fprintf(mfile, "%i %i %i\n",i+1,r.comps[j]+1,KK->coeff_to_int(*sparseelems++)); //is *sparseelems integer? } } fprintf(mfile, "0 0 0\n"); fclose(mfile); }
void F4GB::show_new_rows_matrix() { int ncols = INTSIZE(mat->columns); int nrows = 0; for (int nr=0; nr<mat->rows.size(); nr++) if (is_new_GB_row(nr)) nrows++; MutableMatrix *gbM = IM2_MutableMatrix_make(KK->get_ring(), nrows, ncols, false); int r = -1; for (int nr=0; nr<mat->rows.size(); nr++) if (is_new_GB_row(nr)) { r++; row_elem &row = mat->rows[nr]; ring_elem *rowelems = newarray(ring_elem, row.len); if (row.coeffs == 0) { if (row.monom == 0) KK->to_ringelem_array(row.len, gens[row.elem]->f.coeffs, rowelems); else KK->to_ringelem_array(row.len, gb[row.elem]->f.coeffs, rowelems); } else { KK->to_ringelem_array(row.len, row.coeffs, rowelems); } for (int i=0; i<row.len; i++) { int c = row.comps[i]; gbM->set_entry(r,c,rowelems[i]); } deletearray(rowelems); } buffer o; gbM->text_out(o); emit(o.str()); }
void F4GB::process_s_pair(spair *p) { int c; switch (p->type) { case F4_SPAIR_SPAIR: { packed_monomial n = next_monom; M->unchecked_divide(p->lcm, gb[p->i]->f.monoms, n); B.intern(1+M->monomial_size(n)); next_monom = B.reserve(1+M->max_monomial_size()); next_monom++; load_row(n, p->i); c = mat->rows[mat->rows.size()-1].comps[0]; if (mat->columns[c].head >= -1) n_lcmdups++; else { // In this situation, we load the other half as a reducer n = next_monom; M->unchecked_divide(p->lcm, gb[p->j]->f.monoms, n); B.intern(1+M->monomial_size(n)); next_monom = B.reserve(1+M->max_monomial_size()); next_monom++; load_row(n, p->j); mat->columns[c].head = INTSIZE(mat->rows)-1; } break; } case F4_SPAIR_GEN: load_gen(p->i); break; default: break; } }
void gbB::auto_reduce_by(int id) { /* Loop backwards while degree doesn't change */ /* Don't change quotient ring elements */ gbelem *me = gb[id]; int a = me->gap; // Only auto reduce those that are of the same degree // and not a higher gap level for (int i= INTSIZE(gb)-1; i>=first_gb_element; i--) { if (i == id) continue; gbelem *g = gb[i]; if (g->deg < me->deg) return; if (g->gap < a) continue; if (M2_gbTrace >= 10) { buffer o; o << " auto reduce " << i << " by " << id; emit_line(o.str()); } R->gbvector_auto_reduce(F, Fsyz, g->g.f, g->g.fsyz, // these are modified me->g.f, me->g.fsyz); } }
// 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::insert_gb(POLY f, gbelem_type minlevel) { /* Reduce this element as far as possible. This either removes content, makes it monic, or at least negates it so the lead coeff is positive. */ ring_elem junk; //DEBUG BLOCK int fwt; // int fdeg = weightInfo->gbvector_weight(f.f, fwt); // fprintf(stderr, "inserting GB element %d, thisdeg %d deg %d gap %d\n", // gb.size(), // this_degree, // fdeg, // fdeg-fwt); remainder(f,this_degree,false,junk); // fdeg = weightInfo->gbvector_weight(f.f, fwt); // fprintf(stderr, " after remainder deg %d gap %d\n", // fdeg, // fdeg-fwt); stats_ngb++; // Complete hack for getting bug fix to get test/isSubset.m2 to work again for 1.3: // over ZZ, always make gb elements non reducers... gbelem *g = gbelem_make(f.f, f.fsyz, minlevel, this_degree); minimal_gb_valid = false; int me = INTSIZE(gb); gb.push_back(g); n_gb++; int x = g->g.f->comp; // In a encoded Schreyer order, the following line might miss subring elements. // But it at least won't be incorrect... if (R->get_flattened_monoid()->in_subring(1,g->g.f->monom)) n_subring++; lookup->insert(g->lead, x, me); if (M2_gbTrace == 15) { buffer o; o << " new "; gbelem_text_out(o, INTSIZE(gb)-1); emit_line(o.str()); } else if (M2_gbTrace >= 5) { char s[100]; buffer o; sprintf(s, "new-inserting element %d (minimal %d): ",me,minlevel); o << s; R->gbvector_text_out(o,F,g->g.f); emit_line(o.str()); o.reset(); o << " syzygy : "; R->gbvector_text_out(o,Fsyz,g->g.fsyz); emit_line(o.str()); } auto_reduce_by(me); if (hilbert) { bool is_last_elem = hilbert->addMonomial(g->lead, x); if (is_last_elem) flush_pairs(); } else { #ifdef DEVELOPMENT #warning "todo: codimension stop condition" #endif // codim test is set. Compute the codimension now. } if (M2_gbTrace >= 10) { // show(); } }
void F4GB::do_spairs() { if (hilbert && hilbert->nRemainingExpected() == 0) { if (M2_gbTrace >= 1) fprintf(stderr, "-- skipping degree...no elements expected in this degree\n"); return; } reset_matrix(); reset_syz_matrix(); clock_t begin_time = clock(); n_lcmdups = 0; make_matrix(); if (M2_gbTrace >= 5) { fprintf(stderr, "---------\n"); show_matrix(); fprintf(stderr, "---------\n"); } clock_t end_time = clock(); clock_make_matrix += end_time - begin_time; double nsecs = static_cast<double>(end_time - begin_time); nsecs /= CLOCKS_PER_SEC; if (M2_gbTrace >= 2) fprintf(stderr, " make matrix time = %f\n", nsecs); if (M2_gbTrace >= 2) H.dump(); begin_time = clock(); gauss_reduce(true); end_time = clock(); clock_gauss += end_time - begin_time; // fprintf(stderr, "---------\n"); // show_matrix(); // fprintf(stderr, "---------\n"); nsecs = static_cast<double>(end_time - begin_time); nsecs /= CLOCKS_PER_SEC; if (M2_gbTrace >= 2) { fprintf(stderr, " gauss time = %f\n", nsecs); fprintf(stderr, " lcm dups = %ld\n", n_lcmdups); if (M2_gbTrace >= 5) { fprintf(stderr, "---------\n"); show_matrix(); fprintf(stderr, "---------\n"); show_syz_matrix(); // show_new_rows_matrix(); } } new_GB_elements(); int ngb = INTSIZE(gb); if (M2_gbTrace >= 1) { fprintf(stderr, " # GB elements = %d\n", ngb); if (M2_gbTrace >= 5) show_gb_array(gb); if (using_syz) fprintf(stderr, " # syzygies = %ld\n", static_cast<long>(syz_basis.size())); if (M2_gbTrace >= 5) show_syz_basis(); } clear_matrix(); clear_syz_matrix(); }
void F4GB::tail_reduce() { int nrows = INTSIZE(mat->rows); int ncols = INTSIZE(mat->columns); KK->dense_row_allocate(gauss_row, ncols); if (using_syz) KK->dense_row_allocate(syz_row, nrows); for (int i=nrows-1; i>=0; i--) { row_elem &r = mat->rows[i]; if (r.len <= 1 || r.coeffs == 0) continue; // row reduced to zero, ignore it. // At this point, we should have an element to reduce bool anychange = false; KK->dense_row_fill_from_sparse(gauss_row, r.len, r.coeffs, r.comps); syz_dense_row_fill_from_sparse(i); // fill syz_row from row[i] int firstnonzero = r.comps[0]; int first = (r.len == 1 ? ncols : r.comps[1]); int last = r.comps[r.len-1]; while (first <= last) { int pivotrow = mat->columns[first].head; if (pivotrow >= 0) { anychange = true; row_elem &pivot_rowelem = mat->rows[pivotrow]; // pivot_rowelems.coeffs is set at this point syzygy_row_record_reduction(pivotrow, KK->lead_coeff(r.coeffs), KK->lead_coeff(pivot_rowelem.coeffs)); KK->dense_row_cancel_sparse(gauss_row, pivot_rowelem.len, pivot_rowelem.coeffs, pivot_rowelem.comps); int last1 = pivot_rowelem.comps[pivot_rowelem.len-1]; if (last1 > last) last = last1; } else if (firstnonzero == ncols) firstnonzero = first; first = KK->dense_row_next_nonzero(gauss_row, first+1, last); }; if (anychange) { Mem->components.deallocate(r.comps); KK->deallocate_F4CCoefficientArray(r.coeffs, r.len); // the coeff array is owned by the row here r.len = 0; KK->dense_row_to_sparse_row(gauss_row, r.len, r.coeffs, r.comps, firstnonzero, last); if (using_syz) { row_elem& s = syz->rows[i]; if (s.len>0) // the opposite should not happen { int* scoeffs = static_cast<int *>(s.coeffs); Mem->coefficients.deallocate(scoeffs); Mem->components.deallocate(s.comps); s.len = 0; } syz_dense_row_to_sparse_row(syz->rows[i]); // the above line leaves syz_row zero } } else { KK->dense_row_clear(gauss_row, firstnonzero, last); KK->dense_row_clear(gauss_row, 0, INTSIZE(syz->columns)-1); //!!!lazy } if (r.len > 0) { syzygy_row_divide(i, static_cast<int*>(r.coeffs)[0]); KK->sparse_row_make_monic(r.len, r.coeffs); } } KK->dense_row_deallocate(gauss_row); if (using_syz) KK->dense_row_deallocate(syz_row); }
void F4GB::gauss_reduce(bool diagonalize) // This reduces the matrix to a triangular form { // For each row which is a non-pivot row: // note that the row must be reducible, since the lead term corresponds to an spair cancellation // actually: not true: generators will often not be reducible... // also each such row must be non-zero, for the same reason int nrows = INTSIZE(mat->rows); int ncols = INTSIZE(mat->columns); int n_newpivots = -1; // the number of new GB elements in this degree int n_zero_reductions = 0; if (hilbert) { n_newpivots = hilbert->nRemainingExpected(); if (n_newpivots == 0) return; } KK->dense_row_allocate(gauss_row, ncols); if (using_syz) KK->dense_row_allocate(syz_row, nrows); for (int i=0; i<nrows; i++) { row_elem &r = mat->rows[i]; if (r.len == 0) continue; // could happen once we include syzygies... int pivotcol = r.comps[0]; int pivotrow = mat->columns[pivotcol].head; if (pivotrow == i) continue; // this is a pivot row, so leave it alone F4CoefficientArray rcoeffs = get_coeffs_array(r); n_pairs_computed++; KK->dense_row_fill_from_sparse(gauss_row, r.len, rcoeffs, r.comps); syz_dense_row_fill_from_sparse(i); // fill syz_row from row[i] int firstnonzero = ncols; int first = r.comps[0]; int last = r.comps[r.len-1]; do { pivotrow = mat->columns[first].head; if (pivotrow >= 0) { row_elem &pivot_rowelem = mat->rows[pivotrow]; F4CoefficientArray pivot_coeffs = get_coeffs_array(pivot_rowelem); syzygy_row_record_reduction(pivotrow, KK->lead_coeff(rcoeffs), KK->lead_coeff(pivot_coeffs)); n_reduction_steps++; KK->dense_row_cancel_sparse(gauss_row, pivot_rowelem.len, pivot_coeffs, pivot_rowelem.comps); int last1 = pivot_rowelem.comps[pivot_rowelem.len-1]; if (last1 > last) last = last1; } else if (firstnonzero == ncols) firstnonzero = first; first = KK->dense_row_next_nonzero(gauss_row, first+1, last); } while (first <= last); if (r.coeffs) KK->deallocate_F4CCoefficientArray(r.coeffs, r.len); Mem->components.deallocate(r.comps); r.len = 0; KK->dense_row_to_sparse_row(gauss_row, r.len, r.coeffs, r.comps, firstnonzero, last); // the above line leaves gauss_row zero, and also handles the case when r.len is 0 // it also potentially frees the old r.coeffs and r.comps if (using_syz) { row_elem& s = syz->rows[i]; if (s.len>0) // the opposite should not happen { int* scoeffs = static_cast<int *>(s.coeffs); Mem->coefficients.deallocate(scoeffs); Mem->components.deallocate(s.comps); s.len = 0; } syz_dense_row_to_sparse_row(syz->rows[i]); // the above line leaves syz_row zero } if (r.len > 0) { syzygy_row_divide(i, static_cast<int*>(r.coeffs)[0]); KK->sparse_row_make_monic(r.len, r.coeffs); mat->columns[r.comps[0]].head = i; if (--n_newpivots == 0) break; } else n_zero_reductions++; } KK->dense_row_deallocate(gauss_row); if (using_syz) KK->dense_row_deallocate(syz_row); if (M2_gbTrace >= 3) fprintf(stderr, "-- #zeroreductions %d\n", n_zero_reductions); if (diagonalize) tail_reduce(); }
void F4GB::reorder_columns() { // Set up to sort the columns. // Result is an array 0..ncols-1, giving the new order. // Find the inverse of this permutation: place values into "ord" column fields. // Loop through every element of the matrix, changing its comp array. int nrows = INTSIZE(mat->rows); int ncols = INTSIZE(mat->columns); // sort the columns int *column_order = Mem->components.allocate(ncols); int *ord = Mem->components.allocate(ncols); ColumnsSorter C(M, mat); // Actual sort of columns ///////////////// #if 0 //TODO: MES remove the code in this ifdef 0 C.reset_ncomparisons(); clock_t begin_time = clock(); for (int i=0; i<ncols; i++) { column_order[i] = i; } if (M2_gbTrace >= 2) fprintf(stderr, "ncomparisons = "); QuickSorter<ColumnsSorter>::sort(&C, column_order, ncols); clock_t end_time = clock(); if (M2_gbTrace >= 2) fprintf(stderr, "%ld, ", C.ncomparisons()); double nsecs = (double)(end_time - begin_time)/CLOCKS_PER_SEC; clock_sort_columns += nsecs; if (M2_gbTrace >= 2) fprintf(stderr, " time = %f\n", nsecs); #endif // STL version /////////////// C.reset_ncomparisons(); clock_t begin_time0 = clock(); for (int i=0; i<ncols; i++) { column_order[i] = i; } if (M2_gbTrace >= 2) fprintf(stderr, "ncomparisons = "); std::stable_sort(column_order, column_order+ncols, C); clock_t end_time0 = clock(); if (M2_gbTrace >= 2) fprintf(stderr, "%ld, ", C.ncomparisons0()); double nsecs0 = (double)(end_time0 - begin_time0)/CLOCKS_PER_SEC; clock_sort_columns += nsecs0; if (M2_gbTrace >= 2) fprintf(stderr, " time = %f\n", nsecs0); //////////////////////////// for (int i=0; i<ncols; i++) { ord[column_order[i]] = i; } // Now move the columns into position coefficient_matrix::column_array newcols; newcols.reserve(ncols); for (int i=0; i<ncols; i++) { long newc = column_order[i]; newcols.push_back(mat->columns[newc]); } // Now reset the components in each row for (int r=0; r<nrows; r++) { row_elem &row = mat->rows[r]; for (int i=0; i<row.len; i++) { int oldcol = row.comps[i]; int newcol = ord[oldcol]; row.comps[i] = newcol; } for (int i=1; i<row.len; i++) { if (row.comps[i] <= row.comps[i-1]) { fprintf(stderr, "Internal error: array out of order\n"); break; } } } std::swap(mat->columns, newcols); Mem->components.deallocate(column_order); Mem->components.deallocate(ord); }