source: git/Singular/MinorProcessor.cc @ b08f6fe

spielwiese
Last change on this file since b08f6fe was b08f6fe, checked in by Frank Seelisch <seelisch@…>, 14 years ago
code for extended minor command git-svn-id: file:///usr/local/Singular/svn/trunk@12490 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 50.9 KB
Line 
1#include "mod2.h"
2#include "structs.h"
3#include "polys.h"
4#include <MinorProcessor.h>
5#include "febase.h"
6#include "kstd1.h"
7#include "kbuckets.h"
8
9void MinorProcessor::print() const {
10    PrintS(this->toString().c_str());
11}
12
13int MinorProcessor::getBestLine (const int k, const MinorKey& mk) const {
14    // This method identifies the row or column with the most zeros.
15    // The returned index (bestIndex) is absolute within the pre-defined matrix.
16    // If some row has the most zeros, then the absolute (0-based) row index is returned.
17    // If, contrariwise, some column has the most zeros, then -1 minus the absolute (0-based) column index is returned.
18    int numberOfZeros = 0;
19    int bestIndex = 100000;    // We start with an invalid row/column index.
20    int maxNumberOfZeros = -1; // We update this variable whenever we find a new so-far optimal row or column.
21    for (int r = 0; r < k; r++) {
22        // iterate through all k rows of the momentary minor
23        int absoluteR = mk.getAbsoluteRowIndex(r);
24        numberOfZeros = 0;
25        for (int c = 0; c < k; c++) {
26            int absoluteC = mk.getAbsoluteColumnIndex(c);
27            if (isEntryZero(absoluteR, absoluteC)) numberOfZeros++;
28        }
29        if (numberOfZeros > maxNumberOfZeros) {
30            // We found a new best line which is a row.
31            bestIndex = absoluteR;
32            maxNumberOfZeros = numberOfZeros;
33        }
34    };
35    for (int c = 0; c < k; c++) {
36        int absoluteC = mk.getAbsoluteColumnIndex(c);
37        numberOfZeros = 0;
38        for (int r = 0; r < k; r++) {
39            int absoluteR = mk.getAbsoluteRowIndex(r);
40            if (isEntryZero(absoluteR, absoluteC)) numberOfZeros++;
41        }
42        if (numberOfZeros > maxNumberOfZeros) {
43            // We found a new best line which is a column. So we transform the return value.
44            // Note that we can easily get back absoluteC from bestLine: absoluteC = - 1 - bestLine.
45            bestIndex = - absoluteC - 1;
46            maxNumberOfZeros = numberOfZeros;
47        }
48    };
49    return bestIndex;
50}
51
52void MinorProcessor::setMinorSize(const int minorSize) {
53    _minorSize = minorSize;
54    _minor.reset();
55}
56
57bool MinorProcessor::hasNextMinor() {
58    return setNextKeys(_minorSize);
59}
60
61void MinorProcessor::getCurrentRowIndices(int* const target) const {
62    return _minor.getAbsoluteRowIndices(target);
63}
64
65void MinorProcessor::getCurrentColumnIndices(int* const target) const {
66    return _minor.getAbsoluteColumnIndices(target);
67}
68
69void MinorProcessor::defineSubMatrix(const int numberOfRows, const int* rowIndices,
70                                     const int numberOfColumns, const int* columnIndices) {
71    // The method assumes ascending row and column indices in the two argument arrays.
72    // These indices are understood to be zero-based.
73    // The method will set the two arrays of ints in _container.
74    // Example: The indices 0, 2, 3, 7 will be converted to an array with one int
75    // representing the binary number 10001101 (check bits from right to left).
76
77    _containerRows = numberOfRows;
78    int highestRowIndex = rowIndices[numberOfRows - 1];
79    int rowBlockCount = (highestRowIndex / 32) + 1;
80    unsigned int rowBlocks[rowBlockCount];
81    for (int i = 0; i < rowBlockCount; i++) rowBlocks[i] = 0;
82    for (int i = 0; i < numberOfRows; i++) {
83        int blockIndex = rowIndices[i] / 32;
84        int offset = rowIndices[i] % 32;
85        rowBlocks[blockIndex] += (1 << offset);
86    }
87
88    _containerColumns = numberOfColumns;
89    int highestColumnIndex = columnIndices[numberOfColumns - 1];
90    int columnBlockCount = (highestColumnIndex / 32) + 1;
91    unsigned int columnBlocks[columnBlockCount];
92    for (int i = 0; i < columnBlockCount; i++) columnBlocks[i] = 0;
93    for (int i = 0; i < numberOfColumns; i++) {
94        int blockIndex = columnIndices[i] / 32;
95        int offset = columnIndices[i] % 32;
96        columnBlocks[blockIndex] += (1 << offset);
97    }
98
99    _container.set(rowBlockCount, rowBlocks, columnBlockCount, columnBlocks);
100}
101
102bool MinorProcessor::setNextKeys(const int k) {
103    // This method moves _minor to the next valid kxk-minor within _container.
104    // It returns true iff this is successful, i.e. iff _minor did not already encode the final kxk-minor.
105    if (_minor.compare(MinorKey(0, 0, 0, 0)) == 0) {
106        // This means that we haven't started yet. Thus, we are about to compute the first kxk-minor.
107        _minor.selectFirstRows(k, _container);
108        _minor.selectFirstColumns(k, _container);
109        return true;
110    }
111    else if (_minor.selectNextColumns(k, _container)) {
112        // Here we were able to pick a next subset of columns (within the same subset of rows).
113        return true;
114    }
115    else if (_minor.selectNextRows(k, _container)) {
116        // Here we were not able to pick a next subset of columns (within the same subset of rows).
117        // But we could pick a next subset of rows. We must hence reset the subset of columns:
118        _minor.selectFirstColumns(k, _container);
119        return true;
120    }
121    else {
122        // We were neither able to pick a next subset of columns nor of rows.
123        // I.e., we have iterated through all sensible choices of subsets of rows and columns.
124        return false;
125    }
126}
127
128bool MinorProcessor::isEntryZero (const int absoluteRowIndex, const int absoluteColumnIndex) const
129{
130  assume(false);
131  return false;
132}
133
134string MinorProcessor::toString () const
135{
136  assume(false);
137  return "";
138}
139
140int MinorProcessor::IOverJ(const int i, const int j) {
141    // This is a non-recursive implementation.
142    assert(i >= 0 && j >= 0 && i >= j);
143    if (j == 0 || i == j) return 1;
144    int result = 1;
145    for (int k = i - j + 1; k <= i; k++) result *= k;
146    // Here, we have result = (i - j + 1) * ... * i.
147    for (int k = 2; k <= j; k++) result /= k;
148    // Here, we have result = (i - j + 1) * ... * i / 1 / 2 ... / j = i! / j! / (i - j)!.
149    return result;
150}
151
152int MinorProcessor::Faculty(const int i) {
153    // This is a non-recursive implementation.
154    assert(i >= 0);
155    int result = 1;
156    for (int j = 1; j <= i; j++) result *= j;
157    // Here, we have result = 1 * 2 * ... * i = i!
158    return result;
159}
160
161int MinorProcessor::NumberOfRetrievals (const int rows, const int columns, const int containerMinorSize,
162                        const int minorSize, const bool multipleMinors) {
163    // This method computes the number of potential retrievals of a single minor when computing
164    // all minors of a given size within a matrix of given size.
165    int result = 0;
166    if (multipleMinors) {
167        // Here, we would like to compute all minors of size
168        // containerMinorSize x containerMinorSize in a matrix of size rows x columns.
169        // Then, we need to retrieve any minor of size minorSize x minorSize exactly
170        // n times, where n is as follows:
171        result = IOverJ(rows - minorSize, containerMinorSize - minorSize)
172               * IOverJ(columns - minorSize, containerMinorSize - minorSize)
173               * Faculty(containerMinorSize - minorSize);
174    }
175    else {
176        // Here, we would like to compute just one minor of size
177        // containerMinorSize x containerMinorSize. Then, we need to retrieve
178        // any minor of size minorSize x minorSize exactly
179        // (containerMinorSize - minorSize)! times:
180        result = Faculty(containerMinorSize - minorSize);
181    }
182    return result;
183}
184
185MinorProcessor::MinorProcessor () {
186    _container = MinorKey(0, 0, 0, 0);
187    _minor = MinorKey(0, 0, 0, 0);
188    _containerRows = 0;
189    _containerColumns = 0;
190    _minorSize = 0;
191    _rows = 0;
192    _columns = 0;
193}
194
195IntMinorProcessor::IntMinorProcessor () {
196    _intMatrix = 0;
197}
198
199string IntMinorProcessor::toString () const {
200    char h[32];
201    string t = "";
202    string s = "IntMinorProcessor:";
203    s += "\n   matrix: ";
204    sprintf(h, "%d", _rows); s += h;
205    s += " x ";
206    sprintf(h, "%d", _columns); s += h;
207    for (int r = 0; r < _rows; r++) {
208        s += "\n      ";
209        for (int c = 0; c < _columns; c++) {
210            sprintf(h, "%d", getEntry(r, c)); t = h;
211            for (int k = 0; k < int(4 - strlen(h)); k++) s += " ";
212            s += t;
213        }
214    }
215    int myIndexArray[500];
216    s += "\n   considered submatrix has row indices: ";
217    _container.getAbsoluteRowIndices(myIndexArray);
218    for (int k = 0; k < _containerRows; k++) {
219        if (k != 0) s += ", ";
220        sprintf(h, "%d", myIndexArray[k]); s += h;
221    }
222    s += " (first row of matrix has index 0)";
223    s += "\n   considered submatrix has column indices: ";
224    _container.getAbsoluteColumnIndices(myIndexArray);
225    for (int k = 0; k < _containerColumns; k++) {
226        if (k != 0) s += ", ";
227        sprintf(h, "%d", myIndexArray[k]); s += h;
228    }
229    s += " (first column of matrix has index 0)";
230    s += "\n   size of considered minor(s): ";
231    sprintf(h, "%d", _minorSize); s += h;
232    s += "x";
233    s += h;
234    return s;
235}
236
237IntMinorProcessor::~IntMinorProcessor() {
238    // free memory of _intMatrix
239    delete [] _intMatrix; _intMatrix = 0;
240}
241
242bool IntMinorProcessor::isEntryZero (const int absoluteRowIndex, const int absoluteColumnIndex) const
243{
244  return getEntry(absoluteRowIndex, absoluteColumnIndex) == 0;
245}
246
247void IntMinorProcessor::defineMatrix (const int numberOfRows, const int numberOfColumns, const int* matrix) {
248    // free memory of _intMatrix
249    delete [] _intMatrix; _intMatrix = 0;
250
251    _rows = numberOfRows;
252    _columns = numberOfColumns;
253
254    // allocate memory for new entries in _intMatrix
255    int n = _rows * _columns;
256    _intMatrix = new int[n];
257
258    // copying values from one-dimensional method parameter "matrix"
259    for (int i = 0; i < n; i++)
260      _intMatrix[i] = matrix[i];
261}
262
263IntMinorValue IntMinorProcessor::getMinor(const int dimension, const int* rowIndices, const int* columnIndices,
264                                          Cache<MinorKey, IntMinorValue>& c, const int characteristic, const ideal& iSB) {
265    defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
266    _minorSize = dimension;
267    // call a helper method which recursively computes the minor using the cache c:
268    return getMinorPrivateLaplace(dimension, _container, false, c, characteristic, iSB);
269}
270
271IntMinorValue IntMinorProcessor::getMinor(const int dimension, const int* rowIndices, const int* columnIndices,
272                                          const int characteristic, const ideal& iSB, const char* algorithm) {
273    defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
274    _minorSize = dimension;
275
276    // call a helper method which computes the minor (without using a cache):
277    if (strcmp(algorithm, "Laplace") == 0)
278      return getMinorPrivateLaplace(_minorSize, _container, characteristic, iSB);
279    else if (strcmp(algorithm, "Bareiss") == 0)
280      return getMinorPrivateBareiss(_minorSize, _container, characteristic, iSB);
281    else assume(false);
282}
283
284IntMinorValue IntMinorProcessor::getNextMinor(const int characteristic, const ideal& iSB, const char* algorithm) {
285    // call a helper method which computes the minor (without using a cache):
286    if (strcmp(algorithm, "Laplace") == 0)
287      return getMinorPrivateLaplace(_minorSize, _minor, characteristic, iSB);
288    else if (strcmp(algorithm, "Bareiss") == 0)
289      return getMinorPrivateBareiss(_minorSize, _minor, characteristic, iSB);
290    else assume(false);
291}
292
293IntMinorValue IntMinorProcessor::getNextMinor(Cache<MinorKey, IntMinorValue>& c, const int characteristic, const ideal& iSB) {
294    // computation with cache
295    return getMinorPrivateLaplace(_minorSize, _minor, true, c, characteristic, iSB);
296}
297
298/* compute the reduction of an integer i modulo an ideal which captures a std basis */
299int getReduction (const int i, const ideal& iSB)
300{
301  if (i == 0) return 0;
302  poly f = pISet(i);
303  poly g = kNF(iSB, currRing->qideal, f);
304  int result = 0;
305  if (g != NULL) result = n_Int(pGetCoeff(g), currRing);
306  pDelete(&f);
307  pDelete(&g);
308  return result;
309}
310
311IntMinorValue IntMinorProcessor::getMinorPrivateLaplace(const int k, const MinorKey& mk, const int characteristic, const ideal& iSB) {
312    assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
313    // The method works by recursion, and using Lapace's Theorem along the row/column with the most zeros.
314    if (k == 1) {
315        int e = getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0));
316        if (characteristic != 0) e = e % characteristic;
317        if (iSB != 0) e = getReduction(e, iSB);
318        return IntMinorValue(e, 0, 0, 0, 0, -1, -1); // "-1" is to signal that any statistics about the
319                                                     // number of retrievals does not make sense, as we do not use a cache.
320    }
321    else {
322        // Here, the minor must be 2x2 or larger.
323        int b = getBestLine(k, mk);                          // row or column with most zeros
324        int result = 0;                                      // This will contain the value of the minor.
325        int s = 0; int m = 0; int as = 0; int am = 0;        // counters for additions and multiplications,
326                                                             // ..."a*" for accumulated operation counters
327        if (b >= 0) {
328            // This means that the best line is the row with absolute (0-based) index b.
329            // Using Laplace, the sign of the contributing minors must be iterating;
330            // the initial sign depends on the relative index of b in minorRowKey:
331            int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
332            for (int c = 0; c < k; c++) {
333                int absoluteC = mk.getAbsoluteColumnIndex(c);      // This iterates over all involved columns.
334                if (getEntry(b, absoluteC) != 0) { // Only then do we have to consider this sub-determinante.
335                    MinorKey subMk = mk.getSubMinorKey(b, absoluteC);  // This is mk with row b and column absoluteC omitted.
336                    IntMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, characteristic, iSB);  // recursive call
337                    m += mv.getMultiplications();
338                    s += mv.getAdditions();
339                    am += mv.getAccumulatedMultiplications();
340                    as += mv.getAccumulatedAdditions();
341                    result += sign * mv.getResult() * getEntry(b, absoluteC); // adding sub-determinante times matrix entry
342                                                                              // times appropriate sign
343                    if (characteristic != 0) result = result % characteristic;
344                    s++; m++; as++, am++; // This is for the addition and multiplication in the previous line of code.
345                }
346                sign = - sign; // alternating the sign
347            }
348        }
349        else {
350            b = - b - 1;
351            // This means that the best line is the column with absolute (0-based) index b.
352            // Using Laplace, the sign of the contributing minors must be iterating;
353            // the initial sign depends on the relative index of b in minorColumnKey:
354            int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
355            for (int r = 0; r < k; r++) {
356                int absoluteR = mk.getAbsoluteRowIndex(r);        // This iterates over all involved rows.
357                if (getEntry(absoluteR, b) != 0) { // Only then do we have to consider this sub-determinante.
358                    MinorKey subMk = mk.getSubMinorKey(absoluteR, b); // This is mk with row absoluteR and column b omitted.
359                    IntMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, characteristic, iSB);  // recursive call
360                    m += mv.getMultiplications();
361                    s += mv.getAdditions();
362                    am += mv.getAccumulatedMultiplications();
363                    as += mv.getAccumulatedAdditions();
364                    result += sign * mv.getResult() * getEntry(absoluteR, b); // adding sub-determinante times matrix entry
365                                                                             // times appropriate sign
366                    if (characteristic != 0) result = result % characteristic;
367                    s++; m++; as++, am++; // This is for the addition and multiplication in the previous line of code.
368                }
369                sign = - sign; // alternating the sign
370            }
371        }
372        s--; as--; // first addition was 0 + ..., so we do not count it
373        if (s < 0) s = 0; // may happen when all subminors are zero and no addition needs to be performed
374        if (as < 0) as = 0; // may happen when all subminors are zero and no addition needs to be performed
375        if (iSB != 0) result = getReduction(result, iSB);
376        IntMinorValue newMV(result, m, s, am, as, -1, -1); // "-1" is to signal that any statistics about the
377                                                           // number of retrievals does not make sense, as we
378                                                           // do not use a cache.
379        return newMV;
380    }
381}
382
383/* This can only be used in the case of coefficients coming from a field!!! */
384IntMinorValue IntMinorProcessor::getMinorPrivateBareiss(const int k, const MinorKey& mk, const int characteristic, const ideal& iSB) {
385  assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
386  int theRows[k]; mk.getAbsoluteRowIndices(theRows);
387  int theColumns[k]; mk.getAbsoluteColumnIndices(theColumns);
388  // the next line provides the return value for the case k = 1
389  int e = getEntry(theRows[0], theColumns[0]);
390  if (characteristic != 0) e = e % characteristic;
391  if (iSB != 0) e = getReduction(e, iSB);
392  IntMinorValue mv(e, 0, 0, 0, 0, -1, -1);
393  if (k > 1)
394  {
395    // the matrix to perform Bareiss with
396    long tempMatrix[k * k];
397    // copy correct set of entries from _intMatrix to tempMatrix
398    int i = 0;
399    for (int r = 0; r < k; r++)
400      for (int c = 0; c < k; c++)
401      {
402        e = getEntry(theRows[r], theColumns[c]);
403        if (characteristic != 0) e = e % characteristic;
404        tempMatrix[i++] = e;
405      }
406    // Bareiss algorithm operating on tempMatrix which is at least 2x2
407    int sign = 1;   // This will store the correct sign resulting from permuting the rows of tempMatrix.
408    int rowPermutation[k];   // This is for storing the permutation of rows resulting from searching for a
409                             // non-zero pivot element.
410    for (int i = 0; i < k; i++) rowPermutation[i] = i;
411    int divisor = 1;   // the Bareiss divisor
412    for (int r = 0; r <= k - 2; r++)
413    {
414      // look for a non-zero entry in column r:
415      int i = r;
416      while ((i < k) && (tempMatrix[rowPermutation[i] * k + r] == 0))
417        i++;
418      if (i == k)
419        // There is no non-zero entry; hence the minor is zero.
420        return IntMinorValue(0, 0, 0, 0, 0, -1, -1);
421      if (i != r)
422      {
423        // We swap the rows with indices r and i:
424        int j = rowPermutation[i];
425        rowPermutation[i] = rowPermutation[r];
426        rowPermutation[r] = j;
427        // Now we know that tempMatrix[rowPermutation[r] * k + r] is not zero.
428        // But carefull; we have to negate the sign, as there is always an odd
429        // number of row transpositions to swap two given rows of a matrix.
430        sign = -sign;
431      }
432      if (r >= 1) divisor = tempMatrix[rowPermutation[r - 1] * k + r - 1];
433      for (int rr = r + 1; rr < k; rr++)
434        for (int cc = r + 1; cc < k; cc++)
435        {
436          e = rowPermutation[rr] * k + cc;
437          // Attention: The following may cause an overflow and thus a wrong result:
438          tempMatrix[e] = tempMatrix[e] * tempMatrix[rowPermutation[r] * k + r]
439                         - tempMatrix[rowPermutation[r] * k + cc] * tempMatrix[rowPermutation[rr] * k + r];
440          // The following is, by theory, always a division without remainder:
441          tempMatrix[e] = tempMatrix[e] / divisor;
442          if (characteristic != 0) tempMatrix[e] = tempMatrix[e] % characteristic;
443        }
444    }
445    int theValue = sign * tempMatrix[rowPermutation[k - 1] * k + k - 1];
446    if (iSB != 0) theValue = getReduction(theValue, iSB);
447    mv = IntMinorValue(theValue, 0, 0, 0, 0, -1, -1);
448  }
449  return mv;
450}
451
452int IntMinorProcessor::getEntry (const int rowIndex, const int columnIndex) const
453{
454  return _intMatrix[rowIndex * _columns + columnIndex];
455}
456
457IntMinorValue IntMinorProcessor::getMinorPrivateLaplace(const int k, const MinorKey& mk,
458                                                        const bool multipleMinors,
459                                                        Cache<MinorKey, IntMinorValue>& cch,
460                                                        const int characteristic, const ideal& iSB) {
461    assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
462    // The method works by recursion, and using Lapace's Theorem along the row/column with the most zeros.
463    if (k == 1) {
464        int e = getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0));
465        if (characteristic != 0) e = e % characteristic;
466        if (iSB != 0) e = getReduction(e, iSB);
467        return IntMinorValue(e, 0, 0, 0, 0, -1, -1); // we set "-1" as, for k == 1, we do not have any cache retrievals
468    }
469    else {
470        int b = getBestLine(k, mk);                          // row or column with most zeros
471        int result = 0;                                      // This will contain the value of the minor.
472        int s = 0; int m = 0; int as = 0; int am = 0;        // counters for additions and multiplications,
473                                                             // ..."a*" for accumulated operation counters
474        IntMinorValue mv(0, 0, 0, 0, 0, 0, 0);               // for storing all intermediate minors
475        if (b >= 0) {
476            // This means that the best line is the row with absolute (0-based) index b.
477            // Using Laplace, the sign of the contributing minors must be iterating;
478            // the initial sign depends on the relative index of b in minorRowKey:
479            int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
480            for (int c = 0; c < k; c++) {
481                int absoluteC = mk.getAbsoluteColumnIndex(c);      // This iterates over all involved columns.
482                if (getEntry(b, absoluteC) != 0) { // Only then do we have to consider this sub-determinante.
483                    MinorKey subMk = mk.getSubMinorKey(b, absoluteC);  // This is mk with row b and column absoluteC omitted.
484                    if (cch.hasKey(subMk)) { // trying to find the result in the cache
485                        mv = cch.getValue(subMk);
486                        mv.incrementRetrievals(); // once more, we made use of the cached value for key mk
487                        cch.put(subMk, mv); // We need to do this with "put", as the (altered) number of retrievals may have
488                                            // an impact on the internal ordering among cache entries.
489                    }
490                    else {
491                        mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch, characteristic, iSB); // recursive call
492                        // As this minor was not in the cache, we count the additions and
493                        // multiplications that we needed to do in the recursive call:
494                        m += mv.getMultiplications();
495                        s += mv.getAdditions();
496                    }
497                    // In any case, we count all nested operations in the accumulative counters:
498                    am += mv.getAccumulatedMultiplications();
499                    as += mv.getAccumulatedAdditions();
500                    result += sign * mv.getResult() * getEntry(b, absoluteC); // adding sub-determinante times matrix entry
501                                                                             // times appropriate sign
502                    if (characteristic != 0) result = result % characteristic;
503                    s++; m++; as++; am++; // This is for the addition and multiplication in the previous line of code.
504                }
505                sign = - sign; // alternating the sign
506            }
507        }
508        else {
509            b = - b - 1;
510            // This means that the best line is the column with absolute (0-based) index b.
511            // Using Laplace, the sign of the contributing minors must be iterating;
512            // the initial sign depends on the relative index of b in minorColumnKey:
513            int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
514            for (int r = 0; r < k; r++) {
515                int absoluteR = mk.getAbsoluteRowIndex(r);        // This iterates over all involved rows.
516                if (getEntry(absoluteR, b) != 0) { // Only then do we have to consider this sub-determinante.
517                    MinorKey subMk = mk.getSubMinorKey(absoluteR, b); // This is mk with row absoluteR and column b omitted.
518                    if (cch.hasKey(subMk)) { // trying to find the result in the cache
519                        mv = cch.getValue(subMk);
520                        mv.incrementRetrievals(); // once more, we made use of the cached value for key mk
521                        cch.put(subMk, mv); // We need to do this with "put", as the (altered) number of retrievals may have
522                                            // an impact on the internal ordering among cache entries.
523                    }
524                    else {
525                        mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch, characteristic, iSB); // recursive call
526                        // As this minor was not in the cache, we count the additions and
527                        // multiplications that we needed to do in the recursive call:
528                        m += mv.getMultiplications();
529                        s += mv.getAdditions();
530                    }
531                    // In any case, we count all nested operations in the accumulative counters:
532                    am += mv.getAccumulatedMultiplications();
533                    as += mv.getAccumulatedAdditions();
534                    result += sign * mv.getResult() * getEntry(absoluteR, b); // adding sub-determinante times matrix entry
535                                                                             // times appropriate sign
536                    if (characteristic != 0) result = result % characteristic;
537                    s++; m++; as++; am++; // This is for the addition and multiplication in the previous line of code.
538                }
539                sign = - sign; // alternating the sign
540            }
541        }
542        // Let's cache the newly computed minor:
543        int potentialRetrievals = NumberOfRetrievals(_containerRows, _containerColumns, _minorSize, k, multipleMinors);
544        s--; as--; // first addition was 0 + ..., so we do not count it
545        if (s < 0) s = 0; // may happen when all subminors are zero and no addition needs to be performed
546        if (as < 0) as = 0; // may happen when all subminors are zero and no addition needs to be performed
547        if (iSB != 0) result = getReduction(result, iSB);
548        IntMinorValue newMV(result, m, s, am, as, 1, potentialRetrievals);
549        cch.put(mk, newMV); // Here's the actual put inside the cache.
550        return newMV;
551    }
552}
553
554PolyMinorProcessor::PolyMinorProcessor ()
555{
556  _polyMatrix = 0;
557}
558
559poly PolyMinorProcessor::getEntry (const int rowIndex, const int columnIndex) const
560{
561  return _polyMatrix[rowIndex * _columns + columnIndex];
562}
563
564bool PolyMinorProcessor::isEntryZero (const int absoluteRowIndex, const int absoluteColumnIndex) const
565{
566  return getEntry(absoluteRowIndex, absoluteColumnIndex) == NULL;
567}
568
569string PolyMinorProcessor::toString () const {
570    char h[32];
571    string t = "";
572    string s = "PolyMinorProcessor:";
573    s += "\n   matrix: ";
574    sprintf(h, "%d", _rows); s += h;
575    s += " x ";
576    sprintf(h, "%d", _columns); s += h;
577    int myIndexArray[500];
578    s += "\n   considered submatrix has row indices: ";
579    _container.getAbsoluteRowIndices(myIndexArray);
580    for (int k = 0; k < _containerRows; k++) {
581        if (k != 0) s += ", ";
582        sprintf(h, "%d", myIndexArray[k]); s += h;
583    }
584    s += " (first row of matrix has index 0)";
585    s += "\n   considered submatrix has column indices: ";
586    _container.getAbsoluteColumnIndices(myIndexArray);
587    for (int k = 0; k < _containerColumns; k++) {
588        if (k != 0) s += ", ";
589        sprintf(h, "%d", myIndexArray[k]); s += h;
590    }
591    s += " (first column of matrix has index 0)";
592    s += "\n   size of considered minor(s): ";
593    sprintf(h, "%d", _minorSize); s += h;
594    s += "x";
595    s += h;
596    return s;
597}
598
599PolyMinorProcessor::~PolyMinorProcessor() {
600    // free memory of _polyMatrix
601    int n = _rows * _columns;
602    for (int i = 0; i < n; i++)
603      p_Delete(&_polyMatrix[i], currRing);
604    delete [] _polyMatrix; _polyMatrix = 0;
605}
606
607void PolyMinorProcessor::defineMatrix (const int numberOfRows, const int numberOfColumns, const poly* polyMatrix) {
608    // free memory of _polyMatrix
609    int n = _rows * _columns;
610    for (int i = 0; i < n; i++)
611      p_Delete(&_polyMatrix[i], currRing);
612    delete [] _polyMatrix; _polyMatrix = 0;
613
614    _rows = numberOfRows;
615    _columns = numberOfColumns;
616    n = _rows * _columns;
617
618    // allocate memory for new entries in _polyMatrix
619    _polyMatrix = new poly[n];
620
621    // copying values from one-dimensional method parameter "polyMatrix"
622    for (int i = 0; i < n; i++)
623      _polyMatrix[i] = pCopy(polyMatrix[i]);
624}
625
626PolyMinorValue PolyMinorProcessor::getMinor(const int dimension, const int* rowIndices, const int* columnIndices,
627                                            Cache<MinorKey, PolyMinorValue>& c, const ideal& iSB) {
628    defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
629    _minorSize = dimension;
630    // call a helper method which recursively computes the minor using the cache c:
631    return getMinorPrivateLaplace(dimension, _container, false, c, iSB);
632}
633
634PolyMinorValue PolyMinorProcessor::getMinor(const int dimension, const int* rowIndices, const int* columnIndices,
635                                            const char* algorithm, const ideal& iSB) {
636    defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
637    _minorSize = dimension;
638    // call a helper method which computes the minor (without using a cache):
639    if (strcmp(algorithm, "Laplace") == 0)
640      return getMinorPrivateLaplace(_minorSize, _container, iSB);
641    else if (strcmp(algorithm, "Bareiss") == 0)
642      return getMinorPrivateBareiss(_minorSize, _container, iSB);
643    else assume(false);
644}
645
646PolyMinorValue PolyMinorProcessor::getNextMinor(const char* algorithm, const ideal& iSB) {
647    // call a helper method which computes the minor (without using a cache):
648    if (strcmp(algorithm, "Laplace") == 0)
649      return getMinorPrivateLaplace(_minorSize, _minor, iSB);
650    else if (strcmp(algorithm, "Bareiss") == 0)
651      return getMinorPrivateBareiss(_minorSize, _minor, iSB);
652    else assume(false);
653}
654
655PolyMinorValue PolyMinorProcessor::getNextMinor(Cache<MinorKey, PolyMinorValue>& c, const ideal& iSB) {
656    // computation with cache
657    return getMinorPrivateLaplace(_minorSize, _minor, true, c, iSB);
658}
659
660/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB */
661PolyMinorValue PolyMinorProcessor::getMinorPrivateLaplace(const int k, const MinorKey& mk, const ideal& iSB) {
662    assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
663    // The method works by recursion, and using Lapace's Theorem along the row/column with the most zeros.
664    if (k == 1) {
665      PolyMinorValue pmv(getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0)),
666                         0, 0, 0, 0, -1, -1); // "-1" is to signal that any statistics about the
667                                                 // number of retrievals does not make sense, as we do not use a cache.
668      return pmv;
669    }
670    else {
671        // Here, the minor must be 2x2 or larger.
672        int b = getBestLine(k, mk);                          // row or column with most zeros
673        poly result = NULL;                                  // This will contain the value of the minor.
674        int s = 0; int m = 0; int as = 0; int am = 0;        // counters for additions and multiplications,
675                                                             // ..."a*" for accumulated operation counters
676        if (b >= 0) {
677            // This means that the best line is the row with absolute (0-based) index b.
678            // Using Laplace, the sign of the contributing minors must be iterating;
679            // the initial sign depends on the relative index of b in minorRowKey:
680            int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
681            poly signPoly = NULL;
682            for (int c = 0; c < k; c++) {
683                int absoluteC = mk.getAbsoluteColumnIndex(c);      // This iterates over all involved columns.
684                if (!isEntryZero(b, absoluteC)) { // Only then do we have to consider this sub-determinante.
685                    MinorKey subMk = mk.getSubMinorKey(b, absoluteC);  // This is MinorKey with row b and column absoluteC omitted.
686                    PolyMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, iSB);  // recursive call
687                    m += mv.getMultiplications();
688                    s += mv.getAdditions();
689                    am += mv.getAccumulatedMultiplications();
690                    as += mv.getAccumulatedAdditions();
691                    pDelete(&signPoly);
692                    signPoly = pISet(sign);
693                    poly temp = pp_Mult_qq(mv.getResult(), getEntry(b, absoluteC), currRing);
694                    temp = p_Mult_q(signPoly, temp, currRing);
695                    result = p_Add_q(result, temp, currRing);
696                    signPoly = NULL;
697                    s++; m++; as++, am++; // This is for the addition and multiplication in the previous line of code.
698                }
699                sign = - sign; // alternating the sign
700            }
701        }
702        else {
703            b = - b - 1;
704            // This means that the best line is the column with absolute (0-based) index b.
705            // Using Laplace, the sign of the contributing minors must be iterating;
706            // the initial sign depends on the relative index of b in minorColumnKey:
707            int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
708            poly signPoly = NULL;
709            for (int r = 0; r < k; r++) {
710                int absoluteR = mk.getAbsoluteRowIndex(r);        // This iterates over all involved rows.
711                if (!isEntryZero(absoluteR, b)) { // Only then do we have to consider this sub-determinante.
712                    MinorKey subMk = mk.getSubMinorKey(absoluteR, b); // This is MinorKey with row absoluteR and column b omitted.
713                    PolyMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, iSB);  // recursive call
714                    m += mv.getMultiplications();
715                    s += mv.getAdditions();
716                    am += mv.getAccumulatedMultiplications();
717                    as += mv.getAccumulatedAdditions();
718                    pDelete(&signPoly);
719                    signPoly = pISet(sign);
720                    poly temp = pp_Mult_qq(mv.getResult(), getEntry(absoluteR, b), currRing);
721                    temp = p_Mult_q(signPoly, temp, currRing);
722                    result = p_Add_q(result, temp, currRing);
723                    signPoly = NULL;
724                    s++; m++; as++, am++; // This is for the addition and multiplication in the previous line of code.
725                }
726                sign = - sign; // alternating the sign
727            }
728        }
729        s--; as--; // first addition was 0 + ..., so we do not count it
730        if (s < 0) s = 0; // may happen when all subminors are zero and no addition needs to be performed
731        if (as < 0) as = 0; // may happen when all subminors are zero and no addition needs to be performed
732        if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
733        PolyMinorValue newMV(result, m, s, am, as, -1, -1); // "-1" is to signal that any statistics about the
734                                                            // number of retrievals does not make sense, as we
735                                                            // do not use a cache.
736        pDelete(&result);
737        return newMV;
738    }
739}
740
741/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB */
742PolyMinorValue PolyMinorProcessor::getMinorPrivateLaplace(const int k, const MinorKey& mk,
743                                                          const bool multipleMinors,
744                                                          Cache<MinorKey, PolyMinorValue>& cch,
745                                                          const ideal& iSB) {
746    assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
747    // The method works by recursion, and using Lapace's Theorem along the row/column with the most zeros.
748    if (k == 1) {
749      PolyMinorValue pmv(getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0)),
750                         0, 0, 0, 0, -1, -1); // we set "-1" as, for k == 1, we do not have any cache retrievals
751      return pmv;
752    }
753    else {
754        int b = getBestLine(k, mk);                          // row or column with most zeros
755        poly result = NULL;                                  // This will contain the value of the minor.
756        int s = 0; int m = 0; int as = 0; int am = 0;        // counters for additions and multiplications,
757                                                             // ..."a*" for accumulated operation counters
758        if (b >= 0) {
759            // This means that the best line is the row with absolute (0-based) index b.
760            // Using Laplace, the sign of the contributing minors must be iterating;
761            // the initial sign depends on the relative index of b in minorRowKey:
762            int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
763            poly signPoly = NULL;
764            for (int c = 0; c < k; c++) {
765                int absoluteC = mk.getAbsoluteColumnIndex(c);      // This iterates over all involved columns.
766                if (!isEntryZero(b, absoluteC)) { // Only then do we have to consider this sub-determinante.
767                    PolyMinorValue mv;              // for storing all intermediate minors
768                    MinorKey subMk = mk.getSubMinorKey(b, absoluteC);  // This is mk with row b and column absoluteC omitted.
769                    if (cch.hasKey(subMk)) { // trying to find the result in the cache
770                        mv = cch.getValue(subMk);
771                        mv.incrementRetrievals(); // once more, we made use of the cached value for key mk
772                        cch.put(subMk, mv); // We need to do this with "put", as the (altered) number of retrievals may have
773                                            // an impact on the internal ordering among cache entries.
774                    }
775                    else {
776                        mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch, iSB); // recursive call
777                        // As this minor was not in the cache, we count the additions and
778                        // multiplications that we needed to do in the recursive call:
779                        m += mv.getMultiplications();
780                        s += mv.getAdditions();
781                    }
782                    // In any case, we count all nested operations in the accumulative counters:
783                    am += mv.getAccumulatedMultiplications();
784                    as += mv.getAccumulatedAdditions();
785                    pDelete(&signPoly);
786                    signPoly = pISet(sign);
787                    poly temp = pp_Mult_qq(mv.getResult(), getEntry(b, absoluteC), currRing);
788                    temp = p_Mult_q(signPoly, temp, currRing);
789                    result = p_Add_q(result, temp, currRing);
790                    signPoly = NULL;
791                    s++; m++; as++; am++; // This is for the addition and multiplication in the previous line of code.
792                }
793                sign = - sign; // alternating the sign
794            }
795        }
796        else {
797            b = - b - 1;
798            // This means that the best line is the column with absolute (0-based) index b.
799            // Using Laplace, the sign of the contributing minors must be iterating;
800            // the initial sign depends on the relative index of b in minorColumnKey:
801            int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
802            poly signPoly = NULL;
803            for (int r = 0; r < k; r++) {
804                int absoluteR = mk.getAbsoluteRowIndex(r);        // This iterates over all involved rows.
805                if (!isEntryZero(absoluteR, b)) { // Only then do we have to consider this sub-determinante.
806                    PolyMinorValue mv;              // for storing all intermediate minors
807                    MinorKey subMk = mk.getSubMinorKey(absoluteR, b); // This is mk with row absoluteR and column b omitted.
808                    if (cch.hasKey(subMk)) { // trying to find the result in the cache
809                        mv = cch.getValue(subMk);
810                        mv.incrementRetrievals(); // once more, we made use of the cached value for key mk
811                        cch.put(subMk, mv); // We need to do this with "put", as the (altered) number of retrievals may have
812                                            // an impact on the internal ordering among cache entries.
813                    }
814                    else {
815                        mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch, iSB); // recursive call
816                        // As this minor was not in the cache, we count the additions and
817                        // multiplications that we needed to do in the recursive call:
818                        m += mv.getMultiplications();
819                        s += mv.getAdditions();
820                    }
821                    // In any case, we count all nested operations in the accumulative counters:
822                    am += mv.getAccumulatedMultiplications();
823                    as += mv.getAccumulatedAdditions();
824                    pDelete(&signPoly);
825                    signPoly = pISet(sign);
826                    poly temp = pp_Mult_qq(mv.getResult(), getEntry(absoluteR, b), currRing);
827                    temp = p_Mult_q(signPoly, temp, currRing);
828                    result = p_Add_q(result, temp, currRing);
829                    signPoly = NULL;
830                    s++; m++; as++; am++; // This is for the addition and multiplication in the previous line of code.
831                }
832                sign = - sign; // alternating the sign
833            }
834        }
835        // Let's cache the newly computed minor:
836        int potentialRetrievals = NumberOfRetrievals(_containerRows, _containerColumns, _minorSize, k, multipleMinors);
837        s--; as--; // first addition was 0 + ..., so we do not count it
838        if (s < 0) s = 0; // may happen when all subminors are zero and no addition needs to be performed
839        if (as < 0) as = 0; // may happen when all subminors are zero and no addition needs to be performed
840        if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
841        PolyMinorValue newMV(result, m, s, am, as, 1, potentialRetrievals);
842        pDelete(&result); result = NULL;
843        cch.put(mk, newMV); // Here's the actual put inside the cache.
844        return newMV;
845    }
846}
847
848/* This can only be used in the case of coefficients coming from a field!!! */
849void addOperationBucket(poly& f1, poly& f2, kBucket_pt& bucket)
850{
851  /* fills all terms of f1 * f2 into the bucket */
852  poly a = f1; poly b = f2;
853  int aLen = pLength(a); int bLen = pLength(b);
854  if (aLen > bLen)
855  {
856    b = f1; a = f2; bLen = aLen;
857  }
858  pNormalize(b);
859
860  while (a != NULL)
861  {
862    /* The next line actually uses only LT(a): */
863    kBucket_Plus_mm_Mult_pp(bucket, a, b, bLen);
864    a = pNext(a);
865  }
866}
867
868/* computes the polynomial (p1 * p2 - p3 * p4) and puts result into p1;
869   the method destroys the old value of p1;
870   p2, p3, and p4 may be pNormalize-d but must, apart from that,
871   not be changed;
872   This can only be used in the case of coefficients coming from a field!!! */
873void elimOperationBucketNoDiv(poly &p1, poly &p2, poly &p3, poly &p4)
874{
875  kBucket_pt myBucket = kBucketCreate();
876  addOperationBucket(p1, p2, myBucket);
877  poly p3Neg = pNeg(pCopy(p3));
878  addOperationBucket(p3Neg, p4, myBucket);
879  pDelete(&p3Neg);
880  pDelete(&p1);
881  p1 = kBucketClear(myBucket);
882  kBucketDestroy(&myBucket);
883}
884
885/* computes the polynomial (p1 * p2 - p3 * p4) / p5 and puts result into p1;
886   the method destroys the old value of p1;
887   p2, p3, p4, and p5 may be pNormalize-d but must, apart from that,
888   not be changed;
889   c5 is assumed to be the leading coefficient of p5;
890   p5Len is assumed to be the length of p5;
891   This can only be used in the case of coefficients coming from a field!!! */
892void elimOperationBucket(poly &p1, poly &p2, poly &p3, poly &p4, poly &p5, number &c5, int p5Len)
893{
894  kBucket_pt myBucket = kBucketCreate();
895  addOperationBucket(p1, p2, myBucket);
896  poly p3Neg = pNeg(pCopy(p3));
897  addOperationBucket(p3Neg, p4, myBucket);
898  pDelete(&p3Neg);
899
900  // Now, myBucket contains all terms of p1 * p2 - p3 * p4.
901  // Now we need to perform the polynomial division myBucket / p5
902  // which is known to work without remainder:
903  pDelete(&p1); poly helperPoly = NULL;
904
905  poly bucketLm = pCopy(kBucketGetLm(myBucket));
906  while (bucketLm != NULL)
907  {
908    /* divide bucketLm by the leading term of p5 and put result into bucketLm;
909       we start with the coefficients;
910       note that bucketLm will always represent a term */
911    number coeff = nDiv(pGetCoeff(bucketLm), c5);
912    nNormalize(coeff);
913    pSetCoeff(bucketLm, coeff);
914    /* subtract exponent vector of p5 from that of quotient; modifies quotient */
915    p_ExpVectorSub(bucketLm, p5, currRing);
916    kBucket_Minus_m_Mult_p(myBucket, bucketLm, p5, &p5Len);
917    /* The following lines make bucketLm the new leading term of p1,
918       i.e., put bucketLm in front of everything which is already in p1.
919       Thus, after the while loop, we need to revert p1. */
920    helperPoly = bucketLm;
921    helperPoly->next = p1;
922    p1 = helperPoly;
923
924    bucketLm = pCopy(kBucketGetLm(myBucket));
925  }
926  p1 = pReverse(p1);
927  kBucketDestroy(&myBucket);
928}
929
930/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB
931   This can only be used in the case of coefficients coming from a field!!! */
932PolyMinorValue PolyMinorProcessor::getMinorPrivateBareiss(const int k, const MinorKey& mk, const ideal& iSB) {
933  assert(k > 0); // k is the minor's dimension; the minor must be at least 1x1
934  int theRows[k]; mk.getAbsoluteRowIndices(theRows);
935  int theColumns[k]; mk.getAbsoluteColumnIndices(theColumns);
936  if (k == 1)
937    return PolyMinorValue(getEntry(theRows[0], theColumns[0]), 0, 0, 0, 0, -1, -1);
938  else /* k > 0 */
939  {
940    // the matrix to perform Bareiss with
941    poly* tempMatrix = (poly*)omAlloc(k * k * sizeof(poly));
942    // copy correct set of entries from _polyMatrix to tempMatrix
943    int i = 0;
944    for (int r = 0; r < k; r++)
945      for (int c = 0; c < k; c++)
946        tempMatrix[i++] = pCopy(getEntry(theRows[r], theColumns[c]));
947
948    // Bareiss algorithm operating on tempMatrix which is at least 2x2
949    int sign = 1;   // This will store the correct sign resulting from permuting the rows of tempMatrix.
950    int rowPermutation[k];   // This is for storing the permutation of rows resulting from searching for a
951                             // non-zero pivot element.
952    for (int i = 0; i < k; i++) rowPermutation[i] = i;
953    poly divisor = NULL;
954    int divisorLength = 0;
955    number divisorLC;
956    for (int r = 0; r <= k - 2; r++)
957    {
958      /* look for a non-zero entry in column r, rows = r .. (k - 1)
959         s.t. the polynomial has least complexity: */
960      int minComplexity = -1; int complexity = 0; int bestRow = -1; poly pp = NULL;
961      for (int i = r; i < k; i++)
962      {
963        pp = tempMatrix[rowPermutation[i] * k + r];
964        if (pp != NULL)
965        {
966          if (minComplexity == -1)
967          {
968            minComplexity = pSize(pp);
969            bestRow = i;
970          }
971          else
972          {
973            complexity = 0;
974            while ((pp != NULL) && (complexity < minComplexity)) { complexity += nSize(pGetCoeff(pp)); pp = pNext(pp); }
975            if (complexity < minComplexity)
976            {
977              minComplexity = complexity;
978              bestRow = i;
979            }
980          }
981          if (minComplexity <= 1) break; /* terminate the search */
982        }
983      }
984      if (bestRow == -1)
985      {
986        // There is no non-zero entry; hence the minor is zero.
987        for (int i = 0; i < k * k; i++) pDelete(&tempMatrix[i]);
988        return PolyMinorValue(NULL, 0, 0, 0, 0, -1, -1);
989      }
990      pNormalize(tempMatrix[rowPermutation[bestRow] * k + r]);
991      if (bestRow != r)
992      {
993        // We swap the rows with indices r and i:
994        int j = rowPermutation[bestRow];
995        rowPermutation[bestRow] = rowPermutation[r];
996        rowPermutation[r] = j;
997        // Now we know that tempMatrix[rowPermutation[r] * k + r] is not zero.
998        // But carefull; we have to negate the sign, as there is always an odd
999        // number of row transpositions to swap two given rows of a matrix.
1000        sign = -sign;
1001      }
1002      if (r != 0)
1003      {
1004        divisor = tempMatrix[rowPermutation[r - 1] * k + r - 1];
1005        pNormalize(divisor);
1006        divisorLength = pLength(divisor);
1007        divisorLC = pGetCoeff(divisor);
1008      }
1009      for (int rr = r + 1; rr < k; rr++)
1010        for (int cc = r + 1; cc < k; cc++)
1011        {
1012          if (r == 0)
1013            elimOperationBucketNoDiv(tempMatrix[rowPermutation[rr] * k + cc],
1014                                     tempMatrix[rowPermutation[r]  * k + r],
1015                                     tempMatrix[rowPermutation[r]  * k + cc],
1016                                     tempMatrix[rowPermutation[rr] * k + r]);
1017          else
1018            elimOperationBucket(tempMatrix[rowPermutation[rr] * k + cc],
1019                                tempMatrix[rowPermutation[r]  * k + r],
1020                                tempMatrix[rowPermutation[r]  * k + cc],
1021                                tempMatrix[rowPermutation[rr] * k + r],
1022                                divisor, divisorLC, divisorLength);
1023        }
1024    }
1025    poly result = tempMatrix[rowPermutation[k - 1] * k + k - 1];
1026    if (sign == -1) result = pNeg(result);
1027    if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
1028    PolyMinorValue mv(result, 0, 0, 0, 0, -1, -1);
1029    for (int i = 0; i < k * k; i++) pDelete(&tempMatrix[i]);
1030    omFreeSize(tempMatrix, k * k * sizeof(poly));
1031    return mv;
1032  }
1033}
1034
Note: See TracBrowser for help on using the repository browser.