23#include <gc/gc_allocator.h>
73 mNumThreads(mtbb::numThreads(numThreads)),
74 mScheduler(mNumThreads),
81 (void) n_rows_to_keep;
84 (void) use_max_degree;
103 if (! g0->f.coeffs.isNull())
129 for (
int i = 1; i < f.
len; i++)
133 if (degi > deg) deg = degi;
135 alpha =
static_cast<int>(deg - leaddeg);
136 deg_result =
static_cast<int>(deg);
141 for (
int i = lo; i <= hi; i++)
145 if (g->
f.
len == 0)
continue;
161 mat->columns.push_back(c);
187 return static_cast<int>(
210 for (
int i = 0; i < g.
len; i++)
217 mat->rows.push_back(r);
234 for (
int i = 0; i < g.
len; i++)
240 mat->rows.push_back(r);
252 if (ce.
head >= -1)
return;
299 c =
mat->rows[
mat->rows.size() - 1].comps[0];
301 if (
mat->columns[c].head >= -1)
335 int *column_order =
new int[ncols];
336 int *ord =
new int[ncols];
345 for (
int i = 0; i < ncols; i++)
350 if (
M2_gbTrace >= 2) fprintf(stderr,
"ncomparisons = ");
355 std::stable_sort(column_order, column_order + ncols, C);
362 double nsecs0 = (double)(end_time0 - begin_time0) / CLOCKS_PER_SEC;
364 if (
M2_gbTrace >= 2) fprintf(stderr,
" time = %f\n", nsecs0);
368 for (
int i = 0; i < ncols; i++)
370 ord[column_order[i]] = i;
375 newcols.reserve(ncols);
376 for (
int i = 0; i < ncols; i++)
378 long newc = column_order[i];
379 newcols.push_back(
mat->columns[newc]);
383 for (
int r = 0; r < nrows; r++)
386 for (
int i = 0; i < row.
len; i++)
388 int oldcol = row.
comps[i];
389 int newcol = ord[oldcol];
390 row.
comps[i] = newcol;
392 for (
int i = 1; i < row.
len; i++)
396 fprintf(stderr,
"Internal error: array out of order\n");
403 delete [] column_order;
414 std::vector<long> rowlocs;
416 newrows.reserve(nrows);
417 rowlocs.reserve(nrows);
418 for (
int r = 0; r < nrows; r++) rowlocs.push_back(-1);
420 for (
int c = 0; c < ncols; c++)
422 int oldrow =
mat->columns[c].head;
427 newrows.push_back(
mat->rows[oldrow]);
428 rowlocs[oldrow] = newrow;
429 mat->columns[c].head = newrow;
430 if (
mat->columns[c].head == oldrow)
mat->columns[c].head = newrow;
433 for (
int r = 0; r < nrows; r++)
434 if (rowlocs[r] < 0) newrows.push_back(
mat->rows[r]);
449 for (
auto & r :
mat->rows)
452 if (not r.coeffs.isNull())
456 if (r.comps !=
nullptr)
464 mat->columns.clear();
478 std::pair<bool,spair>
p;
493 "--matrix--%ld by %ld\n",
494 (
long)
mat->rows.size(),
495 (
long)
mat->columns.size());
526 long nrows =
mat->rows.size();
527 long ncols =
mat->columns.size();
528 for (
long i=0; i<nrows; ++i)
534 auto& r =
mat->rows[i];
535 for (
long j=0; j < r.len; ++j)
538 bool is_left =
mat->columns[c].head >= 0;
539 if (is_pivot and is_left) ++stats.
mAEntries;
540 if (is_pivot and not is_left) ++stats.
mBEntries;
541 if (not is_pivot and is_left) ++stats.
mCEntries;
542 if (not is_pivot and not is_left) ++stats.
mDEntries;
558 std::ostringstream
s;
560 s <<
"Quad matrix sizes" << std::endl;
561 s <<
"sizes of quad matrix" << std::endl;
562 s << std::setw(11) <<
" " << std::setw(11) <<
mTopAndLeft << std::setw(11) <<
mRight << std::endl;
563 s << std::setw(11) <<
mTopAndLeft << std::setw(11) <<
"A" << std::setw(11) <<
"B" << std::endl;
564 s << std::setw(11) <<
mBottom << std::setw(11) <<
"C" << std::setw(11) <<
"D" << std::endl;
569 s <<
"Quad matrix entries (no diagonal on A)" << std::endl;
570 s << std::setw(11) <<
" " << std::setw(11) <<
mTopAndLeft << std::setw(11) <<
mRight << std::endl;
576 o <<
s.str().c_str();
598 if (r.
monom ==
nullptr)
623 int n_newpivots = -1;
624 std::atomic<long> n_zero_reductions = 0;
628 std::vector<int> spair_rows;
632 n_newpivots =
hilbert->nRemainingExpected();
633 if (n_newpivots == 0)
635 std::cout <<
"Oh crap, our logic is wrong: should not get here if no new GB elements expected in this degree" << std::endl;
640 for (
int i = 0; i < nrows; ++i)
643 spair_rows.push_back(i);
646 t0 = mtbb::tick_count::now();
650 std::mutex cout_guard;
651 using threadLocalDense_t = mtbb::enumerable_thread_specific<ElementArray>;
653 threadLocalDense_t threadLocalDense([&]() {
659 std::cout <<
"Number of Threads Used: " << mNumThreads << std::endl;
662 mScheduler.execute([&] {
663 mtbb::parallel_for(mtbb::blocked_range<int>{0,
INTSIZE(spair_rows)},
664 [&](
const mtbb::blocked_range<int>& r)
677 threadLocalDense_t::reference my_dense = threadLocalDense.local();
678 for (
auto i = r.begin(); i != r.end(); ++i)
684 for (
auto tlDense : threadLocalDense)
691 for (
int i = 0; i <
INTSIZE(spair_rows); ++i)
698 t1 = mtbb::tick_count::now();
702 std::cout <<
"About to do serial loop, n_newpivots = " << n_newpivots << std::endl;
703 t0 = mtbb::tick_count::now();
705 for (
auto i = 0; i < spair_rows.size(); i++)
707 auto this_row = spair_rows[i];
708 if ((not
hilbert) or (n_newpivots > 0))
711 if (newNonzeroReduction)
715 mat->columns[r.
comps[0]].head = this_row;
729 t1 = mtbb::tick_count::now();
733 fprintf(stderr,
"-- #zeroreductions %ld\n", n_zero_reductions.load());
735 t0 = mtbb::tick_count::now();
737 t1 = mtbb::tick_count::now();
744 int pivotcol = r.
comps[0];
745 int pivotrow =
mat->columns[pivotcol].head;
746 return (pivotrow == index);
755 if (r.
len == 0)
return false;
758 int pivotcol = r.
comps[0];
759 int pivotrow =
mat->columns[pivotcol].head;
765 int firstnonzero = -1;
766 int first = r.
comps[0];
770 pivotrow =
mat->columns[first].head;
779 pivot_rowelem.
comps + pivot_rowelem.
len)
781 int last1 = pivot_rowelem.
comps[pivot_rowelem.
len - 1];
782 if (last1 > last) last = last1;
784 else if (firstnonzero == -1)
785 firstnonzero = first;
788 while (first <= last);
823 for (
int i = nrows - 1; i >= 0; i--)
829 bool anychange =
false;
832 int firstnonzero = r.
comps[0];
833 int first = (r.
len == 1 ? ncols : r.
comps[1]);
835 while (first <= last)
837 int pivotrow =
mat->columns[first].head;
846 pivot_rowelem.
comps + pivot_rowelem.
len));
847 int last1 = pivot_rowelem.
comps[pivot_rowelem.
len - 1];
848 if (last1 > last) last = last1;
850 else if (firstnonzero == ncols)
851 firstnonzero = first;
909 int nlongs = r.
len * nslots;
935 for (
int i = 0; i < r.
len; i++)
970 mtbb::tick_count t0 = mtbb::tick_count::now();
972 mtbb::tick_count t1 = mtbb::tick_count::now();
992 mtbb::tick_count t0 = mtbb::tick_count::now();
993 for (
int r = 0; r <
mat->rows.size(); r++)
1000 mtbb::tick_count t1 = mtbb::tick_count::now();
1012 mSPairSet.discardSPairsInCurrentDegree();
1015 "-- skipping degree...no elements expected in this degree\n");
1026 fprintf(stderr,
"---------\n");
1028 fprintf(stderr,
"---------\n");
1033 double nsecs =
static_cast<double>(end_time - begin_time);
1034 nsecs /= CLOCKS_PER_SEC;
1035 if (
M2_gbTrace >= 2) fprintf(stderr,
" make matrix time = %f\n", nsecs);
1045 begin_time = clock();
1054 nsecs =
static_cast<double>(end_time - begin_time);
1055 nsecs /= CLOCKS_PER_SEC;
1058 fprintf(stderr,
" gauss time = %f\n", nsecs);
1059 fprintf(stderr,
" parallel gauss time = %g\n",
mParallelGaussTime - oldParallelGauss);
1060 fprintf(stderr,
" serial gauss time = %g\n",
mSerialGaussTime - oldSerialGauss);
1061 fprintf(stderr,
" tail reduce time = %g\n",
mTailReduceTime - oldTailReduce);
1063 fprintf(stderr,
" lcm dups = %ld\n",
n_lcmdups);
1066 fprintf(stderr,
"---------\n");
1068 fprintf(stderr,
"---------\n");
1074 fprintf(stderr,
" finding new spair time = %g\n",
mNewSPairTime - oldNewSPair);
1075 fprintf(stderr,
" number of spairs in queue = %zu\n",
mSPairSet.numberOfSPairs());
1082 fprintf(stderr,
" # GB elements = %d\n", ngb);
1105#warning "compute the codimension"
1125 fprintf(stderr,
"---Just inserted element %d---\n", i);
1153 auto thisDegInfo =
mSPairSet.setThisDegree();
1155 if (not thisDegInfo.first)
1185 "DEGREE %d (nexpected %d npairs %d)\n",
1187 hilbert->nRemainingExpected(),
1190 fprintf(stderr,
"DEGREE %d (npairs %d)\n",
this_degree, npairs);
1207 "total time for making matrix (includes sort): %f\n",
1210 "total time for gauss: %f\n",
1213 "parallel tbb time for gauss: %g\n",
1216 "serial tbb time for gauss: %g\n",
1219 "total time for finding new spairs: %g\n",
1222 "total time for creating pre spairs: %g\n",
1225 "total time for minimizing new spairs: %g\n",
1228 "total time for inserting new gb elements: %g\n",
1231 "number of spairs computed : %ld\n",
1234 "number of reduction steps : %ld\n",
1239 "number of spairs removed by criterion = %ld\n",
1258 for (
int i = 0; i < g.size(); i++)
1262 o <<
"element " << i <<
" degree " << g[i]->deg <<
" alpha "
1263 << g[i]->alpha <<
newline <<
" ";
1273 for (
int i = 0; i <
mat->rows.size(); i++)
1275 fprintf(stderr,
"%4d ",
mat->rows[i].elem);
1276 if (
mat->rows[i].monom ==
nullptr)
1277 fprintf(stderr,
"generator");
1280 fprintf(stderr,
"\n");
1288 for (
int i = 0; i <
mat->columns.size(); i++)
1290 fprintf(stderr,
"head %4d monomial ",
mat->columns[i].head);
1292 fprintf(stderr,
"\n");
1310 for (
int nr = 0; nr <
mat->rows.size(); nr++)
1317 for (
int nr = 0; nr <
mat->rows.size(); nr++)
1323 for (
int i = 0; i < row.
len; i++)
1325 int c = row.
comps[i];
Append-only GC-backed byte buffer used throughout the engine for text output.
void reset_ncomparisons()
long ncomparisons0() const
Comparator that orders Macaulay-matrix column indices by the monomial each column represents,...
Type-erased owning handle to a dense coefficient vector held by a ConcreteVectorArithmetic<Ring>.
void set_hilbert_function(const RingElement *hf)
int mult_monomials(packed_monomial m, packed_monomial n)
const ElementArray & get_coeffs_array(row_elem &r)
void show_new_rows_matrix()
M2_arrayint component_degrees
F4MemoryBlock< monomial_word > mMonomialMemoryBlock
void delete_gb_array(gb_array &g)
int complete_thru_this_degree
enum ComputationStatusCode start_computation(StopConditions &stop_)
void show_gb_array(const gb_array &g) const
bool is_new_GB_row(int row) const
F4GB(const VectorArithmetic *VA, const MonomialInfo *MI, const FreeModule *F, M2_bool collect_syz, int n_rows_to_keep, M2_arrayint gb_weights, int strategy, M2_bool use_max_degree, int max_degree, int numThreads)
void new_generators(int lo, int hi)
MacaulayMatrixStats macaulayMatrixStats() const
monomial_word * next_monom
clock_t clock_make_matrix
HilbertController * hilbert
void load_row(packed_monomial monom, int which)
int find_or_append_column(packed_monomial m)
void show_column_info() const
bool is_pivot_row(int index) const
void show_row_info() const
const MonomialInfo * mMonomialInfo
enum ComputationStatusCode computation_is_complete(StopConditions &stop_)
void poly_set_degrees(const GBF4Polynomial &f, int °_result, int &alpha) const
void loadReducerRow(spair *p)
const FreeModule * mFreeModule
double clock_sort_columns
void gauss_reduce(bool diagonalize)
MonomialLookupTable mLookupTable
void process_s_pair(spair *p)
void insert_gb_element(row_elem &r)
double mParallelGaussTime
MonomialHashTable< MonomialInfo > mMonomialHashTable
void process_column(int c)
void loadSPairRow(spair *p)
const VectorArithmetic * mVectorArithmetic
int new_column(packed_monomial m)
bool gauss_reduce_row(int index, ElementArray &gauss_row)
static MutableMatrix * to_M2_MutableMatrix(const VectorArithmetic *VA, coefficient_matrix *mat, gb_array &gens, gb_array &gb)
static vec to_M2_vec(const VectorArithmetic *VA, const MonomialInfo *MI, const GBF4Polynomial &f, const FreeModule *F)
Engine-side free module R^n over a Ring.
Hilbert-function-driven early termination helper used by F4GB to skip degrees the user-supplied Hilbe...
Per-ring monomial layout / encoding helper used by F4GB.
void text_out(buffer &o) const
virtual bool set_entry(size_t r, size_t c, const ring_elem a)=0
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Runtime dispatcher that hides the concrete coefficient ring behind a std::variant of ConcreteVectorAr...
@ COMP_DONE_SUBRING_LIMIT
Engine error-reporting primitives: ERROR, INTERNAL_ERROR, error, error_message.
F4toM2Interface — static translators between engine vec / Matrix and F4's GBF4Polynomial.
F4SPairSet — priority-queue + pruning logic for F4 S-pairs.
std::vector< gbelem * > gb_array
Shared type vocabulary used across the F4 engine.
F4GB — the inner-loop Faugère F4 Groebner-basis algorithm.
FreeModule — finite-rank free module R^n, the type-level anchor for every Matrix.
HilbertController — early-exit driver for F4 given a known Hilbert series.
bool system_interrupted()
system_interrupted() — thread-safe polling predicate for Ctrl+C handling.
VALGRIND_MAKE_MEM_DEFINED & result(result)
MutableMatrix — abstract base of every mutable matrix the engine hands across the boundary.
F4MemoryBlock<T, NSLAB> — F4's templated slab bump allocator.
MonomialHashTable<ValueType> — open-addressing intern table for F4 and resolution monomials.
monomial_word * packed_monomial
MonomialInfo — F4's packed_monomial encoding plus operations.
MutableMatrix * IM2_MutableMatrix_make(const Ring *R, int nrows, int ncols, M2_bool is_dense)
Engine-boundary C API for the engine's in-place MutableMatrix, including dense linear algebra.
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Ring — the legacy abstract base class for every coefficient and polynomial ring.
ring_elem — the universal value type carried by every Ring* in the engine.
Per-degree counters describing the shape and density of the Macaulay matrix that F4GB just built.
Compact polynomial layout used inside the F4 GB engine.
unsigned int subring_limit
unsigned int basis_element_limit
M2_bool stop_after_degree
Bundle of optional early-termination knobs the front end can attach to a long-running Computation.
std::vector< column_elem > column_array
std::vector< row_elem > row_array
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
double seconds(DurationType time_diff)
varpower_word * varpower_monomial
varpower_monomials::Exponent varpower_word
F4's (variable, exponent) sparse-monomial ExponentList specialisation (legacy).