source: git/Singular/MinorProcessor.cc @ c90500

spielwiese
Last change on this file since c90500 was 762407, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
config.h is for sources files only FIX: config.h should only be used by source (not from inside kernel/mod2.h!) NOTE: each source file should better include mod2.h right after config.h, while headers should better not include mod2.h.
  • Property mode set to 100644
File size: 58.7 KB
Line 
1#include <MinorProcessor.h>
2
3#include "config.h"
4#include <kernel/mod2.h>
5#include <kernel/structs.h>
6#include <kernel/polys.h>
7#include <kernel/febase.h>
8#include <kernel/kstd1.h>
9#include <polys/kbuckets.h>
10
11#ifdef COUNT_AND_PRINT_OPERATIONS
12long addsPoly        = 0;    /* for the number of additions of two polynomials */
13long multsPoly       = 0;    /* for the number of multiplications of two polynomials */
14long addsPolyForDiv  = 0;    /* for the number of additions of two polynomials for
15                                polynomial division part */
16long multsPolyForDiv = 0;    /* for the number of multiplications of two polynomials
17                                for polynomial division part */
18long multsMon        = 0;    /* for the number of multiplications of two monomials */
19long multsMonForDiv  = 0;    /* for the number of m-m-multiplications for polynomial
20                                division part */
21long savedMultsMFD   = 0;    /* number of m-m-multiplications that could be saved
22                                when polynomial division would be optimal
23                                (if p / t1 = t2 + ..., then t1 * t2 = LT(p), i.e.,
24                                this multiplication need not be performed which
25                                would save one m-m-multiplication) */
26long divsMon         = 0;    /* for the number of divisions of two monomials;
27                                these are all guaranteed to work, i.e., m1/m2 only
28                                when exponentVector(m1) >= exponentVector(m2) */
29void printCounters (char* prefix, bool resetToZero)
30{
31  printf("%s [p+p(div) | p*p(div) | m*m(div, -save) | m/m ]", prefix);
32  printf(" = [%ld(%ld) | %ld(%ld) | %ld(%d, -%ld) | %ld]\n",
33         addsPoly, addsPolyForDiv, multsPoly, multsPolyForDiv,
34         multsMon, multsMonForDiv, savedMultsMFD, divsMon);
35  if (resetToZero)
36  {
37    multsMon = 0; addsPoly = 0; multsPoly = 0; divsMon = 0;
38    savedMultsMFD = 0; multsMonForDiv = 0; addsPolyForDiv = 0;
39    multsPolyForDiv = 0;
40  }
41}
42#endif
43/* COUNT_AND_PRINT_OPERATIONS */
44
45void MinorProcessor::print() const
46{
47  PrintS(this->toString().c_str());
48}
49
50int MinorProcessor::getBestLine (const int k, const MinorKey& mk) const
51{
52  /* This method identifies the row or column with the most zeros.
53     The returned index (bestIndex) is absolute within the pre-
54     defined matrix.
55     If some row has the most zeros, then the absolute (0-based)
56     row index is returned.
57     If, contrariwise, some column has the most zeros, then -1 minus
58     the absolute (0-based) column index is returned. */
59  int numberOfZeros = 0;
60  int bestIndex = 100000;    /* We start with an invalid row/column index. */
61  int maxNumberOfZeros = -1; /* We update this variable whenever we find
62                                a new so-far optimal row or column. */
63  for (int r = 0; r < k; r++)
64  {
65    /* iterate through all k rows of the momentary minor */
66    int absoluteR = mk.getAbsoluteRowIndex(r);
67    numberOfZeros = 0;
68    for (int c = 0; c < k; c++)
69    {
70      int absoluteC = mk.getAbsoluteColumnIndex(c);
71      if (isEntryZero(absoluteR, absoluteC)) numberOfZeros++;
72    }
73    if (numberOfZeros > maxNumberOfZeros)
74    {
75      /* We found a new best line which is a row. */
76      bestIndex = absoluteR;
77      maxNumberOfZeros = numberOfZeros;
78    }
79  };
80  for (int c = 0; c < k; c++)
81  {
82    int absoluteC = mk.getAbsoluteColumnIndex(c);
83    numberOfZeros = 0;
84    for (int r = 0; r < k; r++)
85    {
86      int absoluteR = mk.getAbsoluteRowIndex(r);
87      if (isEntryZero(absoluteR, absoluteC)) numberOfZeros++;
88    }
89    if (numberOfZeros > maxNumberOfZeros)
90    {
91      /* We found a new best line which is a column. So we transform
92         the return value. Note that we can easily retrieve absoluteC
93         from bestLine: absoluteC = - 1 - bestLine. */
94      bestIndex = - absoluteC - 1;
95      maxNumberOfZeros = numberOfZeros;
96    }
97  };
98  return bestIndex;
99}
100
101void MinorProcessor::setMinorSize(const int minorSize)
102{
103  _minorSize = minorSize;
104  _minor.reset();
105}
106
107bool MinorProcessor::hasNextMinor()
108{
109  return setNextKeys(_minorSize);
110}
111
112void MinorProcessor::getCurrentRowIndices(int* const target) const
113{
114  return _minor.getAbsoluteRowIndices(target);
115}
116
117void MinorProcessor::getCurrentColumnIndices(int* const target) const
118{
119  return _minor.getAbsoluteColumnIndices(target);
120}
121
122void MinorProcessor::defineSubMatrix(const int numberOfRows,
123                                     const int* rowIndices,
124                                     const int numberOfColumns,
125                                     const int* columnIndices)
126{
127  /* The method assumes ascending row and column indices in the
128     two argument arrays. These indices are understood to be zero-based.
129     The method will set the two arrays of ints in _container.
130     Example: The indices 0, 2, 3, 7 will be converted to an array with
131     one int representing the binary number 10001101
132     (check bits from right to left). */
133
134  _containerRows = numberOfRows;
135  int highestRowIndex = rowIndices[numberOfRows - 1];
136  int rowBlockCount = (highestRowIndex / 32) + 1;
137  unsigned int *rowBlocks=new unsigned int[rowBlockCount];
138  for (int i = 0; i < rowBlockCount; i++) rowBlocks[i] = 0;
139  for (int i = 0; i < numberOfRows; i++)
140  {
141    int blockIndex = rowIndices[i] / 32;
142    int offset = rowIndices[i] % 32;
143    rowBlocks[blockIndex] += (1 << offset);
144  }
145
146  _containerColumns = numberOfColumns;
147  int highestColumnIndex = columnIndices[numberOfColumns - 1];
148  int columnBlockCount = (highestColumnIndex / 32) + 1;
149  unsigned *columnBlocks=new unsigned[columnBlockCount];
150  for (int i = 0; i < columnBlockCount; i++) columnBlocks[i] = 0;
151  for (int i = 0; i < numberOfColumns; i++)
152  {
153    int blockIndex = columnIndices[i] / 32;
154    int offset = columnIndices[i] % 32;
155    columnBlocks[blockIndex] += (1 << offset);
156  }
157
158  _container.set(rowBlockCount, rowBlocks, columnBlockCount, columnBlocks);
159  delete[] columnBlocks;
160  delete[] rowBlocks;
161}
162
163bool MinorProcessor::setNextKeys(const int k)
164{
165  /* This method moves _minor to the next valid (k x k)-minor within
166     _container. It returns true iff this is successful, i.e. iff
167     _minor did not already encode the terminal (k x k)-minor. */
168  if (_minor.compare(MinorKey(0, 0, 0, 0)) == 0)
169  {
170    /* This means that we haven't started yet. Thus, we are about
171       to compute the first (k x k)-minor. */
172    _minor.selectFirstRows(k, _container);
173    _minor.selectFirstColumns(k, _container);
174    return true;
175  }
176  else if (_minor.selectNextColumns(k, _container))
177  {
178    /* Here we were able to pick a next subset of columns
179       within the same subset of rows. */
180    return true;
181  }
182  else if (_minor.selectNextRows(k, _container))
183  {
184    /* Here we were not able to pick a next subset of columns
185       within the same subset of rows. But we could pick a next
186       subset of rows. We must hence reset the subset of columns: */
187    _minor.selectFirstColumns(k, _container);
188    return true;
189  }
190  else
191  {
192    /* We were neither able to pick a next subset
193       of columns nor of rows. I.e., we have iterated through
194       all sensible choices of subsets of rows and columns. */
195    return false;
196  }
197}
198
199bool MinorProcessor::isEntryZero (const int absoluteRowIndex,
200                                  const int absoluteColumnIndex) const
201{
202  assume(false);
203  return false;
204}
205
206string MinorProcessor::toString () const
207{
208  assume(false);
209  return "";
210}
211
212int MinorProcessor::IOverJ(const int i, const int j)
213{
214  /* This is a non-recursive implementation. */
215  assert( (i >= 0) && (j >= 0) && (i >= j));
216  if (j == 0 || i == j) return 1;
217  int result = 1;
218  for (int k = i - j + 1; k <= i; k++) result *= k;
219  /* Now, result = (i - j + 1) * ... * i. */
220  for (int k = 2; k <= j; k++) result /= k;
221  /* Now, result = (i - j + 1) * ... * i / 1 / 2 ...
222     ... / j = i! / j! / (i - j)!. */
223  return result;
224}
225
226int MinorProcessor::Faculty(const int i)
227{
228  /* This is a non-recursive implementation. */
229  assert(i >= 0);
230  int result = 1;
231  for (int j = 1; j <= i; j++) result *= j;
232  // Now, result = 1 * 2 * ... * i = i!
233  return result;
234}
235
236int MinorProcessor::NumberOfRetrievals (const int rows, const int columns,
237                                        const int containerMinorSize,
238                                        const int minorSize,
239                                        const bool multipleMinors)
240{
241  /* This method computes the number of potential retrievals
242     of a single minor when computing all minors of a given size
243     within a matrix of given size. */
244  int result = 0;
245  if (multipleMinors)
246  {
247    /* Here, we would like to compute all minors of size
248       containerMinorSize x containerMinorSize in a matrix
249       of size rows x columns.
250       Then, we need to retrieve any minor of size
251       minorSize x minorSize exactly n times, where n is as
252       follows: */
253    result = IOverJ(rows - minorSize, containerMinorSize - minorSize)
254           * IOverJ(columns - minorSize, containerMinorSize - minorSize)
255           * Faculty(containerMinorSize - minorSize);
256  }
257  else
258  {
259    /* Here, we would like to compute just one minor of size
260       containerMinorSize x containerMinorSize. Then, we need
261       to retrieve any minor of size minorSize x minorSize exactly
262       (containerMinorSize - minorSize)! times: */
263    result = Faculty(containerMinorSize - minorSize);
264  }
265  return result;
266}
267
268MinorProcessor::MinorProcessor ()
269{
270  _container = MinorKey(0, 0, 0, 0);
271  _minor = MinorKey(0, 0, 0, 0);
272  _containerRows = 0;
273  _containerColumns = 0;
274  _minorSize = 0;
275  _rows = 0;
276  _columns = 0;
277}
278
279MinorProcessor::~MinorProcessor () { }
280
281IntMinorProcessor::IntMinorProcessor ()
282{
283  _intMatrix = 0;
284}
285
286string IntMinorProcessor::toString () const
287{
288  char h[32];
289  string t = "";
290  string s = "IntMinorProcessor:";
291  s += "\n   matrix: ";
292  sprintf(h, "%d", _rows); s += h;
293  s += " x ";
294  sprintf(h, "%d", _columns); s += h;
295  for (int r = 0; r < _rows; r++)
296  {
297    s += "\n      ";
298    for (int c = 0; c < _columns; c++)
299    {
300      sprintf(h, "%d", getEntry(r, c)); t = h;
301      for (int k = 0; k < int(4 - strlen(h)); k++) s += " ";
302      s += t;
303    }
304  }
305  int myIndexArray[500];
306  s += "\n   considered submatrix has row indices: ";
307  _container.getAbsoluteRowIndices(myIndexArray);
308  for (int k = 0; k < _containerRows; k++)
309  {
310    if (k != 0) s += ", ";
311    sprintf(h, "%d", myIndexArray[k]); s += h;
312  }
313  s += " (first row of matrix has index 0)";
314  s += "\n   considered submatrix has column indices: ";
315  _container.getAbsoluteColumnIndices(myIndexArray);
316  for (int k = 0; k < _containerColumns; k++)
317  {
318    if (k != 0) s += ", ";
319    sprintf(h, "%d", myIndexArray[k]); s += h;
320  }
321  s += " (first column of matrix has index 0)";
322  s += "\n   size of considered minor(s): ";
323  sprintf(h, "%d", _minorSize); s += h;
324  s += "x";
325  s += h;
326  return s;
327}
328
329IntMinorProcessor::~IntMinorProcessor()
330{
331  /* free memory of _intMatrix */
332  delete [] _intMatrix; _intMatrix = 0;
333}
334
335bool IntMinorProcessor::isEntryZero (const int absoluteRowIndex,
336                                     const int absoluteColumnIndex) const
337{
338  return getEntry(absoluteRowIndex, absoluteColumnIndex) == 0;
339}
340
341void IntMinorProcessor::defineMatrix (const int numberOfRows,
342                                      const int numberOfColumns,
343                                      const int* matrix)
344{
345  /* free memory of _intMatrix */
346  delete [] _intMatrix; _intMatrix = 0;
347
348  _rows = numberOfRows;
349  _columns = numberOfColumns;
350
351  /* allocate memory for new entries in _intMatrix */
352  int n = _rows * _columns;
353  _intMatrix = new int[n];
354
355  /* copying values from one-dimensional method
356     parameter "matrix" */
357  for (int i = 0; i < n; i++)
358    _intMatrix[i] = matrix[i];
359}
360
361IntMinorValue IntMinorProcessor::getMinor(const int dimension,
362                                          const int* rowIndices,
363                                          const int* columnIndices,
364                                          Cache<MinorKey, IntMinorValue>& c,
365                                          const int characteristic,
366                                          const ideal& iSB)
367{
368  defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
369  _minorSize = dimension;
370  /* call a helper method which recursively computes the minor using the
371     cache c: */
372  return getMinorPrivateLaplace(dimension, _container, false, c,
373                                characteristic, iSB);
374}
375
376IntMinorValue IntMinorProcessor::getMinor(const int dimension,
377                                          const int* rowIndices,
378                                          const int* columnIndices,
379                                          const int characteristic,
380                                          const ideal& iSB,
381                                          const char* algorithm)
382{
383  defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
384  _minorSize = dimension;
385
386  /* call a helper method which computes the minor (without a cache): */
387  if (strcmp(algorithm, "Laplace") == 0)
388    return getMinorPrivateLaplace(_minorSize, _container, characteristic,
389                                  iSB);
390  else if (strcmp(algorithm, "Bareiss") == 0)
391    return getMinorPrivateBareiss(_minorSize, _container, characteristic,
392                                  iSB);
393  else assume(false);
394
395  /* The following code is never reached and just there to make the
396     compiler happy: */
397  return IntMinorValue();
398}
399
400IntMinorValue IntMinorProcessor::getNextMinor(const int characteristic,
401                                              const ideal& iSB,
402                                              const char* algorithm)
403{
404  /* call a helper method which computes the minor (without a cache): */
405  if (strcmp(algorithm, "Laplace") == 0)
406    return getMinorPrivateLaplace(_minorSize, _minor, characteristic, iSB);
407  else if (strcmp(algorithm, "Bareiss") == 0)
408    return getMinorPrivateBareiss(_minorSize, _minor, characteristic, iSB);
409  else assume(false);
410 
411  /* The following code is never reached and just there to make the
412     compiler happy: */
413  return IntMinorValue();
414}
415
416IntMinorValue IntMinorProcessor::getNextMinor(Cache<MinorKey,
417                                              IntMinorValue>& c,
418                                              const int characteristic,
419                                              const ideal& iSB)
420{
421    /* computation with cache */
422    return getMinorPrivateLaplace(_minorSize, _minor, true, c, characteristic,
423                                  iSB);
424}
425
426/* computes the reduction of an integer i modulo an ideal
427   which captures a std basis */
428int getReduction (const int i, const ideal& iSB)
429{
430  if (i == 0) return 0;
431  poly f = pISet(i);
432  poly g = kNF(iSB, currRing->qideal, f);
433  int result = 0;
434  if (g != NULL) result = n_Int(pGetCoeff(g), currRing->cf);
435  pDelete(&f);
436  pDelete(&g);
437  return result;
438}
439
440IntMinorValue IntMinorProcessor::getMinorPrivateLaplace(
441     const int k,
442     const MinorKey& mk,
443     const int characteristic,
444     const ideal& iSB)
445{
446  assert(k > 0); /* k is the minor's dimension; the minor must be at least
447                    1x1 */
448  /* The method works by recursion, and using Lapace's Theorem along the
449     row/column with the most zeros. */
450  if (k == 1)
451  {
452    int e = getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0));
453    if (characteristic != 0) e = e % characteristic;
454    if (iSB != 0) e = getReduction(e, iSB);
455    return IntMinorValue(e, 0, 0, 0, 0, -1, -1); /* "-1" is to signal that any
456                                                    statistics about the number
457                                                    of retrievals does not make
458                                                    sense, as we do not use a
459                                                    cache. */
460  }
461  else
462  {
463    /* Here, the minor must be 2x2 or larger. */
464    int b = getBestLine(k, mk);                   /* row or column with most
465                                                     zeros */
466    int result = 0;                               /* This will contain the
467                                                     value of the minor. */
468    int s = 0; int m = 0; int as = 0; int am = 0; /* counters for additions and
469                                                     multiplications, ..."a*"
470                                                     for accumulated operation
471                                                     counters */
472    bool hadNonZeroEntry = false;
473    if (b >= 0)
474    {
475      /* This means that the best line is the row with absolute (0-based)
476         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++) /* This iterates over all involved columns. */
481      {
482        int absoluteC = mk.getAbsoluteColumnIndex(c);
483        if (getEntry(b, absoluteC) != 0) /* Only then do we have to consider
484                                            this sub-determinante. */
485        {
486          hadNonZeroEntry = true;
487          /* Next MinorKey is mk with row b and column absoluteC omitted: */
488          MinorKey subMk = mk.getSubMinorKey(b, absoluteC);
489          IntMinorValue mv = getMinorPrivateLaplace(k - 1, subMk,
490                             characteristic, iSB);  /* recursive call */
491          m += mv.getMultiplications();
492          s += mv.getAdditions();
493          am += mv.getAccumulatedMultiplications();
494          as += mv.getAccumulatedAdditions();
495          /* adding sub-determinante times matrix entry
496             times appropriate sign: */
497          result += sign * mv.getResult() * getEntry(b, absoluteC);
498
499          if (characteristic != 0) result = result % characteristic;
500          s++; m++; as++, am++; /* This is for the last addition and
501                                   multiplication. */
502        }
503        sign = - sign; /* alternating the sign */
504      }
505    }
506    else
507    {
508      b = - b - 1;
509      /* This means that the best line is the column with absolute (0-based)
510         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
513         minorColumnKey: */
514      int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
515      for (int r = 0; r < k; r++) /* This iterates over all involved rows. */
516      {
517        int absoluteR = mk.getAbsoluteRowIndex(r);
518        if (getEntry(absoluteR, b) != 0) /* Only then do we have to consider
519                                            this sub-determinante. */
520        {
521          hadNonZeroEntry = true;
522          /* Next MinorKey is mk with row absoluteR and column b omitted. */
523          MinorKey subMk = mk.getSubMinorKey(absoluteR, b);
524          IntMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, characteristic, iSB); /* recursive call */
525          m += mv.getMultiplications();
526          s += mv.getAdditions();
527          am += mv.getAccumulatedMultiplications();
528          as += mv.getAccumulatedAdditions();
529          /* adding sub-determinante times matrix entry
530             times appropriate sign: */
531          result += sign * mv.getResult() * getEntry(absoluteR, b);
532          if (characteristic != 0) result = result % characteristic;
533          s++; m++; as++, am++; /* This is for the last addition and
534                                   multiplication. */
535        }
536        sign = - sign; /* alternating the sign */
537      }
538    }
539    if (hadNonZeroEntry)
540    {
541      s--; as--; /* first addition was 0 + ..., so we do not count it */
542    }
543    if (s < 0) s = 0; /* may happen when all subminors are zero and no
544                         addition needs to be performed */
545    if (as < 0) as = 0; /* may happen when all subminors are zero and no
546                           addition needs to be performed */
547    if (iSB != 0) result = getReduction(result, iSB);
548    IntMinorValue newMV(result, m, s, am, as, -1, -1);
549    /* "-1" is to signal that any statistics about the number of retrievals
550       does not make sense, as we do not use a cache. */
551    return newMV;
552  }
553}
554
555/* This method can only be used in the case of coefficients
556   coming from a field or at least from an integral domain. */
557IntMinorValue IntMinorProcessor::getMinorPrivateBareiss(
558     const int k,
559     const MinorKey& mk,
560     const int characteristic,
561     const ideal& iSB)
562{
563  assert(k > 0); /* k is the minor's dimension; the minor must be at least
564                    1x1 */
565  int *theRows=new int[k]; mk.getAbsoluteRowIndices(theRows);
566  int *theColumns=new int[k]; mk.getAbsoluteColumnIndices(theColumns);
567  /* the next line provides the return value for the case k = 1 */
568  int e = getEntry(theRows[0], theColumns[0]);
569  if (characteristic != 0) e = e % characteristic;
570  if (iSB != 0) e = getReduction(e, iSB);
571  IntMinorValue mv(e, 0, 0, 0, 0, -1, -1);
572  if (k > 1)
573  {
574    /* the matrix to perform Bareiss with */
575    long *tempMatrix=new long[k * k];
576    /* copy correct set of entries from _intMatrix to tempMatrix */
577    int i = 0;
578    for (int r = 0; r < k; r++)
579      for (int c = 0; c < k; c++)
580      {
581        e = getEntry(theRows[r], theColumns[c]);
582        if (characteristic != 0) e = e % characteristic;
583        tempMatrix[i++] = e;
584      }
585    /* Bareiss algorithm operating on tempMatrix which is at least 2x2 */
586    int sign = 1;   /* This will store the correct sign resulting
587                       from permuting the rows of tempMatrix. */
588    int *rowPermutation=new int[k];
589                    /* This is for storing the permutation of rows
590                       resulting from searching for a non-zero
591                       pivot element. */
592    for (int i = 0; i < k; i++) rowPermutation[i] = i;
593    int divisor = 1;   /* the Bareiss divisor */
594    for (int r = 0; r <= k - 2; r++)
595    {
596      /* look for a non-zero entry in column r: */
597      int i = r;
598      while ((i < k) && (tempMatrix[rowPermutation[i] * k + r] == 0))
599        i++;
600      if (i == k)
601        /* There is no non-zero entry; hence the minor is zero. */
602        return IntMinorValue(0, 0, 0, 0, 0, -1, -1);
603      if (i != r)
604      {
605        /* We swap the rows with indices r and i: */
606        int j = rowPermutation[i];
607        rowPermutation[i] = rowPermutation[r];
608        rowPermutation[r] = j;
609        /* Now we know that tempMatrix[rowPermutation[r] * k + r] is not zero.
610           But carefull; we have to negate the sign, as there is always an odd
611           number of row transpositions to swap two given rows of a matrix. */
612        sign = -sign;
613      }
614      if (r >= 1) divisor = tempMatrix[rowPermutation[r - 1] * k + r - 1];
615      for (int rr = r + 1; rr < k; rr++)
616        for (int cc = r + 1; cc < k; cc++)
617        {
618          e = rowPermutation[rr] * k + cc;
619          /* Attention: The following may cause an overflow and
620             thus a wrong result: */
621          tempMatrix[e] = tempMatrix[e] * tempMatrix[rowPermutation[r] * k + r]
622                         - tempMatrix[rowPermutation[r] * k + cc]
623                         * tempMatrix[rowPermutation[rr] * k + r];
624          /* The following is, by theory, always a division without
625             remainder: */
626          tempMatrix[e] = tempMatrix[e] / divisor;
627          if (characteristic != 0)
628            tempMatrix[e] = tempMatrix[e] % characteristic;
629        }
630      delete[] rowPermutation;
631      delete[] tempMatrix;
632    }
633    int theValue = sign * tempMatrix[rowPermutation[k - 1] * k + k - 1];
634    if (iSB != 0) theValue = getReduction(theValue, iSB);
635    mv = IntMinorValue(theValue, 0, 0, 0, 0, -1, -1);
636  }
637  delete [] theRows;
638  delete [] theColumns;
639  return mv;
640}
641
642int IntMinorProcessor::getEntry (const int rowIndex,
643                                 const int columnIndex) const
644{
645  return _intMatrix[rowIndex * _columns + columnIndex];
646}
647
648IntMinorValue IntMinorProcessor::getMinorPrivateLaplace(
649     const int k, const MinorKey& mk,
650     const bool multipleMinors,
651     Cache<MinorKey, IntMinorValue>& cch,
652     const int characteristic, const ideal& iSB)
653{
654  assert(k > 0); /* k is the minor's dimension; the minor must be at least
655                    1x1 */
656  /* The method works by recursion, and using Lapace's Theorem along
657     the row/column with the most zeros. */
658  if (k == 1)
659  {
660    int e = getEntry(mk.getAbsoluteRowIndex(0), mk.getAbsoluteColumnIndex(0));
661    if (characteristic != 0) e = e % characteristic;
662    if (iSB != 0) e = getReduction(e, iSB);
663    return IntMinorValue(e, 0, 0, 0, 0, -1, -1);
664    /* we set "-1" as, for k == 1, we do not have any cache retrievals */
665  }
666  else
667  {
668    int b = getBestLine(k, mk);                   /* row or column with
669                                                     most zeros */
670    int result = 0;                               /* This will contain the
671                                                     value of the minor. */
672    int s = 0; int m = 0; int as = 0; int am = 0; /* counters for additions
673                                                     and multiplications,
674                                                     ..."a*" for
675                                                     accumulated operation
676                                                     counters */
677    IntMinorValue mv(0, 0, 0, 0, 0, 0, 0);        /* for storing all
678                                                     intermediate minors */
679    bool hadNonZeroEntry = false;
680    if (b >= 0)
681    {
682      /* This means that the best line is the row with absolute (0-based)
683         index b.
684         Using Laplace, the sign of the contributing minors must be
685         iterating; the initial sign depends on the relative index of b
686         in minorRowKey: */
687      int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
688      for (int c = 0; c < k; c++) /* This iterates over all involved
689                                     columns. */
690      {
691        int absoluteC = mk.getAbsoluteColumnIndex(c);
692        if (getEntry(b, absoluteC) != 0) /* Only then do we have to consider
693                                            this sub-determinante. */
694        {
695          hadNonZeroEntry = true;
696          /* Next MinorKey is mk with row b and column absoluteC omitted. */
697          MinorKey subMk = mk.getSubMinorKey(b, absoluteC);
698          if (cch.hasKey(subMk))
699          { /* trying to find the result in the cache */
700              mv = cch.getValue(subMk);
701              mv.incrementRetrievals(); /* once more, we made use of the cached
702                                           value for key mk */
703              cch.put(subMk, mv); /* We need to do this with "put", as the
704                                     (altered) number of retrievals may have
705                                     an impact on the internal ordering among
706                                     the cached entries. */
707          }
708          else
709          {
710              mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch,
711                   characteristic, iSB); /* recursive call */
712              /* As this minor was not in the cache, we count the additions
713                 and multiplications that we needed to perform in the
714                 recursive call: */
715              m += mv.getMultiplications();
716              s += mv.getAdditions();
717          }
718          /* In any case, we count all nested operations in the accumulative
719             counters: */
720          am += mv.getAccumulatedMultiplications();
721          as += mv.getAccumulatedAdditions();
722          /* adding sub-determinante times matrix entry times appropriate
723             sign */
724          result += sign * mv.getResult() * getEntry(b, absoluteC);
725          if (characteristic != 0) result = result % characteristic;
726          s++; m++; as++; am++; /* This is for the last addition and
727                                   multiplication. */
728        }
729        sign = - sign; /* alternating the sign */
730      }
731    }
732    else
733    {
734      b = - b - 1;
735      /* This means that the best line is the column with absolute (0-based)
736         index b.
737         Using Laplace, the sign of the contributing minors must be iterating;
738         the initial sign depends on the relative index of b in
739         minorColumnKey: */
740      int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
741      for (int r = 0; r < k; r++) /* This iterates over all involved rows. */
742      {
743        int absoluteR = mk.getAbsoluteRowIndex(r);
744        if (getEntry(absoluteR, b) != 0) /* Only then do we have to consider
745                                            this sub-determinante. */
746        {
747          hadNonZeroEntry = true;
748          /* Next MinorKey is mk with row absoluteR and column b omitted. */
749          MinorKey subMk = mk.getSubMinorKey(absoluteR, b);
750          if (cch.hasKey(subMk))
751          { /* trying to find the result in the cache */
752            mv = cch.getValue(subMk);
753            mv.incrementRetrievals(); /* once more, we made use of the cached
754                                         value for key mk */
755            cch.put(subMk, mv); /* We need to do this with "put", as the
756                                   (altered) number of retrievals may have an
757                                   impact on the internal ordering among the
758                                   cached entries. */
759          }
760          else
761          {
762            mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch, characteristic, iSB); /* recursive call */
763            /* As this minor was not in the cache, we count the additions and
764               multiplications that we needed to do in the recursive call: */
765            m += mv.getMultiplications();
766            s += mv.getAdditions();
767          }
768          /* In any case, we count all nested operations in the accumulative
769             counters: */
770          am += mv.getAccumulatedMultiplications();
771          as += mv.getAccumulatedAdditions();
772          /* adding sub-determinante times matrix entry times appropriate
773             sign: */
774          result += sign * mv.getResult() * getEntry(absoluteR, b);
775          if (characteristic != 0) result = result % characteristic;
776          s++; m++; as++; am++; /* This is for the last addition and
777                                   multiplication. */
778        }
779        sign = - sign; /* alternating the sign */
780      }
781    }
782    /* Let's cache the newly computed minor: */
783    int potentialRetrievals = NumberOfRetrievals(_containerRows,
784                                                 _containerColumns,
785                                                 _minorSize, k,
786                                                 multipleMinors);
787    if (hadNonZeroEntry)
788    {
789      s--; as--; /* first addition was 0 + ..., so we do not count it */
790    }
791    if (s < 0) s = 0; /* may happen when all subminors are zero and no
792                         addition needs to be performed */
793    if (as < 0) as = 0; /* may happen when all subminors are zero and no
794                           addition needs to be performed */
795    if (iSB != 0) result = getReduction(result, iSB);
796    IntMinorValue newMV(result, m, s, am, as, 1, potentialRetrievals);
797    cch.put(mk, newMV); /* Here's the actual put inside the cache. */
798    return newMV;
799  }
800}
801
802PolyMinorProcessor::PolyMinorProcessor ()
803{
804  _polyMatrix = 0;
805}
806
807poly PolyMinorProcessor::getEntry (const int rowIndex,
808                                   const int columnIndex) const
809{
810  return _polyMatrix[rowIndex * _columns + columnIndex];
811}
812
813bool PolyMinorProcessor::isEntryZero (const int absoluteRowIndex,
814                                      const int absoluteColumnIndex) const
815{
816  return getEntry(absoluteRowIndex, absoluteColumnIndex) == NULL;
817}
818
819string PolyMinorProcessor::toString () const
820{
821  char h[32];
822  string t = "";
823  string s = "PolyMinorProcessor:";
824  s += "\n   matrix: ";
825  sprintf(h, "%d", _rows); s += h;
826  s += " x ";
827  sprintf(h, "%d", _columns); s += h;
828  int myIndexArray[500];
829  s += "\n   considered submatrix has row indices: ";
830  _container.getAbsoluteRowIndices(myIndexArray);
831  for (int k = 0; k < _containerRows; k++)
832  {
833    if (k != 0) s += ", ";
834    sprintf(h, "%d", myIndexArray[k]); s += h;
835  }
836  s += " (first row of matrix has index 0)";
837  s += "\n   considered submatrix has column indices: ";
838  _container.getAbsoluteColumnIndices(myIndexArray);
839  for (int k = 0; k < _containerColumns; k++)
840  {
841    if (k != 0) s += ", ";
842    sprintf(h, "%d", myIndexArray[k]); s += h;
843  }
844  s += " (first column of matrix has index 0)";
845  s += "\n   size of considered minor(s): ";
846  sprintf(h, "%d", _minorSize); s += h;
847  s += "x";
848  s += h;
849  return s;
850}
851
852PolyMinorProcessor::~PolyMinorProcessor()
853{
854  /* free memory of _polyMatrix */
855  int n = _rows * _columns;
856  for (int i = 0; i < n; i++)
857    p_Delete(&_polyMatrix[i], currRing);
858  delete [] _polyMatrix; _polyMatrix = 0;
859}
860
861void PolyMinorProcessor::defineMatrix (const int numberOfRows,
862                                       const int numberOfColumns,
863                                       const poly* polyMatrix)
864{
865  /* free memory of _polyMatrix */
866  int n = _rows * _columns;
867  for (int i = 0; i < n; i++)
868    p_Delete(&_polyMatrix[i], currRing);
869  delete [] _polyMatrix; _polyMatrix = 0;
870
871  _rows = numberOfRows;
872  _columns = numberOfColumns;
873  n = _rows * _columns;
874
875  /* allocate memory for new entries in _polyMatrix */
876  _polyMatrix = new poly[n];
877
878  /* copying values from one-dimensional method
879     parameter "polyMatrix" */
880  for (int i = 0; i < n; i++)
881    _polyMatrix[i] = pCopy(polyMatrix[i]);
882}
883
884PolyMinorValue PolyMinorProcessor::getMinor(const int dimension,
885                                            const int* rowIndices,
886                                            const int* columnIndices,
887                                            Cache<MinorKey, PolyMinorValue>& c,
888                                            const ideal& iSB)
889{
890  defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
891  _minorSize = dimension;
892  /* call a helper method which recursively computes the minor using the cache
893     c: */
894  return getMinorPrivateLaplace(dimension, _container, false, c, iSB);
895}
896
897PolyMinorValue PolyMinorProcessor::getMinor(const int dimension,
898                                            const int* rowIndices,
899                                            const int* columnIndices,
900                                            const char* algorithm,
901                                            const ideal& iSB)
902{
903  defineSubMatrix(dimension, rowIndices, dimension, columnIndices);
904  _minorSize = dimension;
905  /* call a helper method which computes the minor (without using a cache): */
906  if (strcmp(algorithm, "Laplace") == 0)
907    return getMinorPrivateLaplace(_minorSize, _container, iSB);
908  else if (strcmp(algorithm, "Bareiss") == 0)
909    return getMinorPrivateBareiss(_minorSize, _container, iSB);
910  else assume(false);
911
912  /* The following code is never reached and just there to make the
913     compiler happy: */
914  return PolyMinorValue();
915}
916
917PolyMinorValue PolyMinorProcessor::getNextMinor(const char* algorithm,
918                                                const ideal& iSB)
919{
920  /* call a helper method which computes the minor (without using a
921     cache): */
922  if (strcmp(algorithm, "Laplace") == 0)
923    return getMinorPrivateLaplace(_minorSize, _minor, iSB);
924  else if (strcmp(algorithm, "Bareiss") == 0)
925    return getMinorPrivateBareiss(_minorSize, _minor, iSB);
926  else assume(false);
927   
928  /* The following code is never reached and just there to make the
929     compiler happy: */
930  return PolyMinorValue();
931}
932
933PolyMinorValue PolyMinorProcessor::getNextMinor(Cache<MinorKey,
934                                                PolyMinorValue>& c,
935                                                const ideal& iSB)
936{
937    /* computation with cache */
938    return getMinorPrivateLaplace(_minorSize, _minor, true, c, iSB);
939}
940
941/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB */
942PolyMinorValue PolyMinorProcessor::getMinorPrivateLaplace(const int k,
943                                                          const MinorKey& mk,
944                                                          const ideal& iSB)
945{
946  assert(k > 0); /* k is the minor's dimension; the minor must be at least
947                    1x1 */
948  /* The method works by recursion, and using Lapace's Theorem along the
949     row/column with the most zeros. */
950  if (k == 1)
951  {
952    PolyMinorValue pmv(getEntry(mk.getAbsoluteRowIndex(0),
953                                mk.getAbsoluteColumnIndex(0)),
954                       0, 0, 0, 0, -1, -1);
955    /* "-1" is to signal that any statistics about the number of retrievals
956       does not make sense, as we do not use a cache. */
957    return pmv;
958  }
959  else
960  {
961    /* Here, the minor must be 2x2 or larger. */
962    int b = getBestLine(k, mk);                   /* row or column with most
963                                                     zeros */
964    poly result = NULL;                           /* This will contain the
965                                                     value of the minor. */
966    int s = 0; int m = 0; int as = 0; int am = 0; /* counters for additions
967                                                     and multiplications,
968                                                     ..."a*" for accumulated
969                                                     operation counters */
970    bool hadNonZeroEntry = false;
971    if (b >= 0)
972    {
973      /* This means that the best line is the row with absolute (0-based)
974         index b.
975         Using Laplace, the sign of the contributing minors must be iterating;
976         the initial sign depends on the relative index of b in minorRowKey: */
977      int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
978      poly signPoly = NULL;
979      for (int c = 0; c < k; c++) /* This iterates over all involved columns. */
980      {
981        int absoluteC = mk.getAbsoluteColumnIndex(c);
982        if (!isEntryZero(b, absoluteC)) /* Only then do we have to consider
983                                           this sub-determinante. */
984        {
985          hadNonZeroEntry = true;
986          /* Next MinorKey is mk with row b and column absoluteC omitted. */
987          MinorKey subMk = mk.getSubMinorKey(b, absoluteC);
988          /* recursive call: */
989          PolyMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, iSB);
990          m += mv.getMultiplications();
991          s += mv.getAdditions();
992          am += mv.getAccumulatedMultiplications();
993          as += mv.getAccumulatedAdditions();
994          pDelete(&signPoly);
995          signPoly = pISet(sign);
996          poly temp = pp_Mult_qq(mv.getResult(), getEntry(b, absoluteC),
997                                 currRing);
998          temp = p_Mult_q(signPoly, temp, currRing);
999          result = p_Add_q(result, temp, currRing);
1000#ifdef COUNT_AND_PRINT_OPERATIONS
1001          multsPoly++;
1002          addsPoly++;
1003          multsMon += pLength(mv.getResult()) * pLength(getEntry(b, absoluteC));
1004#endif
1005          signPoly = NULL;
1006          s++; m++; as++, am++; /* This is for the addition and multiplication
1007                                   in the previous lines of code. */
1008        }
1009        sign = - sign; /* alternating the sign */
1010      }
1011    }
1012    else
1013    {
1014      b = - b - 1;
1015      /* This means that the best line is the column with absolute (0-based)
1016         index b.
1017         Using Laplace, the sign of the contributing minors must be iterating;
1018         the initial sign depends on the relative index of b in
1019         minorColumnKey: */
1020      int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
1021      poly signPoly = NULL;
1022      for (int r = 0; r < k; r++) /* This iterates over all involved rows. */
1023      {
1024        int absoluteR = mk.getAbsoluteRowIndex(r);
1025        if (!isEntryZero(absoluteR, b)) /* Only then do we have to consider
1026                                           this sub-determinante. */
1027        {
1028          hadNonZeroEntry = true;
1029          /* This is mk with row absoluteR and column b omitted. */
1030          MinorKey subMk = mk.getSubMinorKey(absoluteR, b);
1031          /* recursive call: */
1032          PolyMinorValue mv = getMinorPrivateLaplace(k - 1, subMk, iSB);
1033          m += mv.getMultiplications();
1034          s += mv.getAdditions();
1035          am += mv.getAccumulatedMultiplications();
1036          as += mv.getAccumulatedAdditions();
1037          pDelete(&signPoly);
1038          signPoly = pISet(sign);
1039          poly temp = pp_Mult_qq(mv.getResult(), getEntry(absoluteR, b),
1040                                 currRing);
1041          temp = p_Mult_q(signPoly, temp, currRing);
1042          result = p_Add_q(result, temp, currRing);
1043#ifdef COUNT_AND_PRINT_OPERATIONS
1044          multsPoly++;
1045          addsPoly++;
1046          multsMon += pLength(mv.getResult()) * pLength(getEntry(absoluteR, b));
1047#endif
1048          signPoly = NULL;
1049          s++; m++; as++, am++; /* This is for the addition and multiplication
1050                                   in the previous lines of code. */
1051        }
1052        sign = - sign; /* alternating the sign */
1053      }
1054    }
1055    if (hadNonZeroEntry)
1056    {
1057      s--; as--; /* first addition was 0 + ..., so we do not count it */
1058#ifdef COUNT_AND_PRINT_OPERATIONS
1059      addsPoly--;
1060#endif
1061    }
1062    if (s < 0) s = 0; /* may happen when all subminors are zero and no
1063                         addition needs to be performed */
1064    if (as < 0) as = 0; /* may happen when all subminors are zero and no
1065                           addition needs to be performed */
1066    if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
1067    PolyMinorValue newMV(result, m, s, am, as, -1, -1);
1068    /* "-1" is to signal that any statistics about the number of retrievals
1069       does not make sense, as we do not use a cache. */
1070    pDelete(&result);
1071    return newMV;
1072  }
1073}
1074
1075/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB */
1076PolyMinorValue PolyMinorProcessor::getMinorPrivateLaplace(
1077     const int k,
1078     const MinorKey& mk,
1079     const bool multipleMinors,
1080     Cache<MinorKey, PolyMinorValue>& cch,
1081     const ideal& iSB)
1082{
1083  assert(k > 0); /* k is the minor's dimension; the minor must be at least
1084                    1x1 */
1085  /* The method works by recursion, and using Lapace's Theorem along
1086     the row/column with the most zeros. */
1087  if (k == 1)
1088  {
1089    PolyMinorValue pmv(getEntry(mk.getAbsoluteRowIndex(0),
1090                                mk.getAbsoluteColumnIndex(0)),
1091                       0, 0, 0, 0, -1, -1);
1092    /* we set "-1" as, for k == 1, we do not have any cache retrievals */
1093    return pmv;
1094  }
1095  else
1096  {
1097    int b = getBestLine(k, mk);                   /* row or column with most
1098                                                     zeros */
1099    poly result = NULL;                           /* This will contain the
1100                                                     value of the minor. */
1101    int s = 0; int m = 0; int as = 0; int am = 0; /* counters for additions
1102                                                     and multiplications,
1103                                                     ..."a*" for accumulated
1104                                                     operation counters */
1105    bool hadNonZeroEntry = false;
1106    if (b >= 0)
1107    {
1108      /* This means that the best line is the row with absolute (0-based)
1109         index b.
1110         Using Laplace, the sign of the contributing minors must be iterating;
1111         the initial sign depends on the relative index of b in
1112         minorRowKey: */
1113      int sign = (mk.getRelativeRowIndex(b) % 2 == 0 ? 1 : -1);
1114      poly signPoly = NULL;
1115      for (int c = 0; c < k; c++) /* This iterates over all involved columns. */
1116      {
1117        int absoluteC = mk.getAbsoluteColumnIndex(c);
1118        if (!isEntryZero(b, absoluteC)) /* Only then do we have to consider
1119                                           this sub-determinante. */
1120        {
1121          hadNonZeroEntry = true;
1122          PolyMinorValue mv; /* for storing all intermediate minors */
1123          /* Next MinorKey is mk with row b and column absoluteC omitted. */
1124          MinorKey subMk = mk.getSubMinorKey(b, absoluteC);
1125          if (cch.hasKey(subMk))
1126          { /* trying to find the result in the cache */
1127            mv = cch.getValue(subMk);
1128            mv.incrementRetrievals(); /* once more, we made use of the cached
1129                                         value for key mk */
1130            cch.put(subMk, mv); /* We need to do this with "put", as the
1131                                   (altered) number of retrievals may have an
1132                                   impact on the internal ordering among cache
1133                                   entries. */
1134          }
1135          else
1136          {
1137            /* recursive call: */
1138            mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch,
1139                                        iSB);
1140            /* As this minor was not in the cache, we count the additions and
1141               multiplications that we needed to do in the recursive call: */
1142            m += mv.getMultiplications();
1143            s += mv.getAdditions();
1144          }
1145          /* In any case, we count all nested operations in the accumulative
1146             counters: */
1147          am += mv.getAccumulatedMultiplications();
1148          as += mv.getAccumulatedAdditions();
1149          pDelete(&signPoly);
1150          signPoly = pISet(sign);
1151          poly temp = pp_Mult_qq(mv.getResult(), getEntry(b, absoluteC),
1152                                 currRing);
1153          temp = p_Mult_q(signPoly, temp, currRing);
1154          result = p_Add_q(result, temp, currRing);
1155#ifdef COUNT_AND_PRINT_OPERATIONS
1156          multsPoly++;
1157          addsPoly++;
1158          multsMon += pLength(mv.getResult()) * pLength(getEntry(b, absoluteC));
1159#endif
1160          signPoly = NULL;
1161          s++; m++; as++; am++; /* This is for the addition and multiplication
1162                                   in the previous lines of code. */
1163        }
1164        sign = - sign; /* alternating the sign */
1165      }
1166    }
1167    else
1168    {
1169      b = - b - 1;
1170      /* This means that the best line is the column with absolute (0-based)
1171         index b.
1172         Using Laplace, the sign of the contributing minors must be iterating;
1173         the initial sign depends on the relative index of b in
1174         minorColumnKey: */
1175      int sign = (mk.getRelativeColumnIndex(b) % 2 == 0 ? 1 : -1);
1176      poly signPoly = NULL;
1177      for (int r = 0; r < k; r++) /* This iterates over all involved rows. */
1178      {
1179        int absoluteR = mk.getAbsoluteRowIndex(r);
1180        if (!isEntryZero(absoluteR, b)) /* Only then do we have to consider
1181                                           this sub-determinante. */
1182        {
1183          hadNonZeroEntry = true;
1184          PolyMinorValue mv; /* for storing all intermediate minors */
1185          /* Next MinorKey is mk with row absoluteR and column b omitted. */
1186          MinorKey subMk = mk.getSubMinorKey(absoluteR, b);
1187          if (cch.hasKey(subMk))
1188          { /* trying to find the result in the cache */
1189            mv = cch.getValue(subMk);
1190            mv.incrementRetrievals(); /* once more, we made use of the cached
1191                                         value for key mk */
1192            cch.put(subMk, mv); /* We need to do this with "put", as the
1193                                   (altered) number of retrievals may have an
1194                                   impact on the internal ordering among the
1195                                   cached entries. */
1196          }
1197          else
1198          {
1199            mv = getMinorPrivateLaplace(k - 1, subMk, multipleMinors, cch,
1200                                        iSB); /* recursive call */
1201            /* As this minor was not in the cache, we count the additions and
1202               multiplications that we needed to do in the recursive call: */
1203            m += mv.getMultiplications();
1204            s += mv.getAdditions();
1205          }
1206          /* In any case, we count all nested operations in the accumulative
1207             counters: */
1208          am += mv.getAccumulatedMultiplications();
1209          as += mv.getAccumulatedAdditions();
1210          pDelete(&signPoly);
1211          signPoly = pISet(sign);
1212          poly temp = pp_Mult_qq(mv.getResult(), getEntry(absoluteR, b),
1213                                 currRing);
1214          temp = p_Mult_q(signPoly, temp, currRing);
1215          result = p_Add_q(result, temp, currRing);
1216#ifdef COUNT_AND_PRINT_OPERATIONS
1217          multsPoly++;
1218          addsPoly++;
1219          multsMon += pLength(mv.getResult()) * pLength(getEntry(absoluteR, b));
1220#endif
1221          signPoly = NULL;
1222          s++; m++; as++; am++; /* This is for the addition and multiplication
1223                                   in the previous lines of code. */
1224        }
1225        sign = - sign; /* alternating the sign */
1226      }
1227    }
1228    /* Let's cache the newly computed minor: */
1229    int potentialRetrievals = NumberOfRetrievals(_containerRows,
1230                                                 _containerColumns,
1231                                                 _minorSize,
1232                                                 k,
1233                                                 multipleMinors);
1234    if (hadNonZeroEntry)
1235    {
1236      s--; as--; /* first addition was 0 + ..., so we do not count it */
1237#ifdef COUNT_AND_PRINT_OPERATIONS
1238      addsPoly--;
1239#endif
1240    }
1241    if (s < 0) s = 0; /* may happen when all subminors are zero and no
1242                         addition needs to be performed */
1243    if (as < 0) as = 0; /* may happen when all subminors are zero and no
1244                           addition needs to be performed */
1245    if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
1246    PolyMinorValue newMV(result, m, s, am, as, 1, potentialRetrievals);
1247    pDelete(&result); result = NULL;
1248    cch.put(mk, newMV); /* Here's the actual put inside the cache. */
1249    return newMV;
1250  }
1251}
1252
1253/* This can only be used in the case of coefficients coming from a field
1254   or at least an integral domain. */
1255void addOperationBucket(poly& f1, poly& f2, kBucket_pt& bucket)
1256{
1257  /* fills all terms of f1 * f2 into the bucket */
1258  poly a = f1; poly b = f2;
1259  int aLen = pLength(a); int bLen = pLength(b);
1260  if (aLen > bLen)
1261  {
1262    b = f1; a = f2; bLen = aLen;
1263  }
1264  pNormalize(b);
1265
1266  while (a != NULL)
1267  {
1268    /* The next line actually uses only LT(a): */
1269    kBucket_Plus_mm_Mult_pp(bucket, a, b, bLen);
1270    a = pNext(a);
1271  }
1272}
1273
1274/* computes the polynomial (p1 * p2 - p3 * p4) and puts result into p1;
1275   the method destroys the old value of p1;
1276   p2, p3, and p4 may be pNormalize-d but must, apart from that,
1277   not be changed;
1278   This can only be used in the case of coefficients coming from a field
1279   or at least an integral domain. */
1280void elimOperationBucketNoDiv(poly &p1, poly &p2, poly &p3, poly &p4)
1281{
1282#ifdef COUNT_AND_PRINT_OPERATIONS
1283  if ((pLength(p1) != 0) && (pLength(p2) != 0))
1284  {
1285    multsPoly++;
1286    multsMon += pLength(p1) * pLength(p2);
1287  }
1288  if ((pLength(p3) != 0) && (pLength(p4) != 0))
1289  {
1290    multsPoly++;
1291    multsMon += pLength(p3) * pLength(p4);
1292  }
1293  if ((pLength(p1) != 0) && (pLength(p2) != 0) &&
1294      (pLength(p3) != 0) && (pLength(p4) != 0))
1295    addsPoly++;
1296#endif
1297  kBucket_pt myBucket = kBucketCreate(currRing);
1298  addOperationBucket(p1, p2, myBucket);
1299  poly p3Neg = pNeg(pCopy(p3));
1300  addOperationBucket(p3Neg, p4, myBucket);
1301  pDelete(&p3Neg);
1302  pDelete(&p1);
1303  p1 = kBucketClear(myBucket);
1304  kBucketDestroy(&myBucket);
1305}
1306
1307/* computes the polynomial (p1 * p2 - p3 * p4) / p5 and puts result into p1;
1308   the method destroys the old value of p1;
1309   p2, p3, p4, and p5 may be pNormalize-d but must, apart from that,
1310   not be changed;
1311   c5 is assumed to be the leading coefficient of p5;
1312   p5Len is assumed to be the length of p5;
1313   This can only be used in the case of coefficients coming from a field
1314   or at least an integral domain. */
1315void elimOperationBucket(poly &p1, poly &p2, poly &p3, poly &p4, poly &p5,
1316                         number &c5, int p5Len)
1317{
1318#ifdef COUNT_AND_PRINT_OPERATIONS
1319  if ((pLength(p1) != 0) && (pLength(p2) != 0))
1320  {
1321    multsPoly++;
1322    multsMon += pLength(p1) * pLength(p2);
1323  }
1324  if ((pLength(p3) != 0) && (pLength(p4) != 0))
1325  {
1326    multsPoly++;
1327    multsMon += pLength(p3) * pLength(p4);
1328  }
1329  if ((pLength(p1) != 0) && (pLength(p2) != 0) &&
1330      (pLength(p3) != 0) && (pLength(p4) != 0))
1331    addsPoly++;
1332#endif
1333  kBucket_pt myBucket = kBucketCreate(currRing);
1334  addOperationBucket(p1, p2, myBucket);
1335  poly p3Neg = pNeg(pCopy(p3));
1336  addOperationBucket(p3Neg, p4, myBucket);
1337  pDelete(&p3Neg);
1338
1339  /* Now, myBucket contains all terms of p1 * p2 - p3 * p4.
1340     Now we need to perform the polynomial division myBucket / p5
1341     which is known to work without remainder: */
1342  pDelete(&p1); poly helperPoly = NULL;
1343
1344  poly bucketLm = pCopy(kBucketGetLm(myBucket));
1345  while (bucketLm != NULL)
1346  {
1347    /* divide bucketLm by the leading term of p5 and put result into bucketLm;
1348       we start with the coefficients;
1349       note that bucketLm will always represent a term */
1350    number coeff = nDiv(pGetCoeff(bucketLm), c5);
1351    nNormalize(coeff);
1352    pSetCoeff(bucketLm, coeff);
1353    /* subtract exponent vector of p5 from that of quotient; modifies
1354       quotient */
1355    p_ExpVectorSub(bucketLm, p5, currRing);
1356#ifdef COUNT_AND_PRINT_OPERATIONS
1357    divsMon++;
1358    multsMonForDiv += p5Len;
1359    multsMon += p5Len;
1360    savedMultsMFD++;
1361    multsPoly++;
1362    multsPolyForDiv++;
1363    addsPoly++;
1364    addsPolyForDiv++;
1365#endif
1366    kBucket_Minus_m_Mult_p(myBucket, bucketLm, p5, &p5Len);
1367    /* The following lines make bucketLm the new leading term of p1,
1368       i.e., put bucketLm in front of everything which is already in p1.
1369       Thus, after the while loop, we need to revert p1. */
1370    helperPoly = bucketLm;
1371    helperPoly->next = p1;
1372    p1 = helperPoly;
1373
1374    bucketLm = pCopy(kBucketGetLm(myBucket));
1375  }
1376  p1 = pReverse(p1);
1377  kBucketDestroy(&myBucket);
1378}
1379
1380/* assumes that all entries in polyMatrix are already reduced w.r.t. iSB
1381   This can only be used in the case of coefficients coming from a field!!! */
1382PolyMinorValue PolyMinorProcessor::getMinorPrivateBareiss(const int k,
1383                                                          const MinorKey& mk,
1384                                                          const ideal& iSB)
1385{
1386  assert(k > 0); /* k is the minor's dimension; the minor must be at least
1387                    1x1 */
1388  int *theRows=new int[k]; mk.getAbsoluteRowIndices(theRows);
1389  int *theColumns=new int[k]; mk.getAbsoluteColumnIndices(theColumns);
1390  if (k == 1)
1391  {
1392    PolyMinorValue tmp=PolyMinorValue(getEntry(theRows[0], theColumns[0]),
1393                          0, 0, 0, 0, -1, -1);
1394    delete[] theColumns;
1395    delete[] theRows;
1396    return tmp;
1397  }
1398  else /* k > 0 */
1399  {
1400    /* the matrix to perform Bareiss with */
1401    poly* tempMatrix = (poly*)omAlloc(k * k * sizeof(poly));
1402    /* copy correct set of entries from _polyMatrix to tempMatrix */
1403    int i = 0;
1404    for (int r = 0; r < k; r++)
1405      for (int c = 0; c < k; c++)
1406        tempMatrix[i++] = pCopy(getEntry(theRows[r], theColumns[c]));
1407
1408    /* Bareiss algorithm operating on tempMatrix which is at least 2x2 */
1409    int sign = 1; /* This will store the correct sign resulting from
1410                     permuting the rows of tempMatrix. */
1411    int *rowPermutation=new int[k];   /* This is for storing the permutation of rows
1412                                resulting from searching for a non-zero pivot
1413                                element. */
1414    for (int i = 0; i < k; i++) rowPermutation[i] = i;
1415    poly divisor = NULL;
1416    int divisorLength = 0;
1417    number divisorLC;
1418    for (int r = 0; r <= k - 2; r++)
1419    {
1420      /* look for a non-zero entry in column r, rows = r .. (k - 1)
1421         s.t. the polynomial has least complexity: */
1422      int minComplexity = -1; int complexity = 0; int bestRow = -1;
1423      poly pp = NULL;
1424      for (int i = r; i < k; i++)
1425      {
1426        pp = tempMatrix[rowPermutation[i] * k + r];
1427        if (pp != NULL)
1428        {
1429          if (minComplexity == -1)
1430          {
1431            minComplexity = pSize(pp);
1432            bestRow = i;
1433          }
1434          else
1435          {
1436            complexity = 0;
1437            while ((pp != NULL) && (complexity < minComplexity))
1438            { 
1439              complexity += nSize(pGetCoeff(pp)); pp = pNext(pp);
1440            }
1441            if (complexity < minComplexity)
1442            {
1443              minComplexity = complexity;
1444              bestRow = i;
1445            }
1446          }
1447          if (minComplexity <= 1) break; /* terminate the search */
1448        }
1449      }
1450      if (bestRow == -1)
1451      {
1452        /* There is no non-zero entry; hence the minor is zero. */
1453        for (int i = 0; i < k * k; i++) pDelete(&tempMatrix[i]);
1454        return PolyMinorValue(NULL, 0, 0, 0, 0, -1, -1);
1455      }
1456      pNormalize(tempMatrix[rowPermutation[bestRow] * k + r]);
1457      if (bestRow != r)
1458      {
1459        /* We swap the rows with indices r and i: */
1460        int j = rowPermutation[bestRow];
1461        rowPermutation[bestRow] = rowPermutation[r];
1462        rowPermutation[r] = j;
1463        /* Now we know that tempMatrix[rowPermutation[r] * k + r] is not zero.
1464           But carefull; we have to negate the sign, as there is always an odd
1465           number of row transpositions to swap two given rows of a matrix. */
1466        sign = -sign;
1467      }
1468#if (defined COUNT_AND_PRINT_OPERATIONS) && (COUNT_AND_PRINT_OPERATIONS > 2)
1469      poly w = NULL; int wl = 0;
1470      printf("matrix after %d steps:\n", r);
1471      for (int u = 0; u < k; u++)
1472      {
1473        for (int v = 0; v < k; v++)
1474        {
1475          if ((v < r) && (u > v))
1476            wl = 0;
1477          else
1478          {
1479            w = tempMatrix[rowPermutation[u] * k + v];
1480            wl = pLength(w);
1481          }
1482          printf("%5d  ", wl);
1483        }
1484        printf("\n");
1485      }
1486      printCounters ("", false);
1487#endif
1488      if (r != 0)
1489      {
1490        divisor = tempMatrix[rowPermutation[r - 1] * k + r - 1];
1491        pNormalize(divisor);
1492        divisorLength = pLength(divisor);
1493        divisorLC = pGetCoeff(divisor);
1494      }
1495      for (int rr = r + 1; rr < k; rr++)
1496        for (int cc = r + 1; cc < k; cc++)
1497        {
1498          if (r == 0)
1499            elimOperationBucketNoDiv(tempMatrix[rowPermutation[rr] * k + cc],
1500                                     tempMatrix[rowPermutation[r]  * k + r],
1501                                     tempMatrix[rowPermutation[r]  * k + cc],
1502                                     tempMatrix[rowPermutation[rr] * k + r]);
1503          else
1504            elimOperationBucket(tempMatrix[rowPermutation[rr] * k + cc],
1505                                tempMatrix[rowPermutation[r]  * k + r],
1506                                tempMatrix[rowPermutation[r]  * k + cc],
1507                                tempMatrix[rowPermutation[rr] * k + r],
1508                                divisor, divisorLC, divisorLength);
1509        }
1510    }
1511#if (defined COUNT_AND_PRINT_OPERATIONS) && (COUNT_AND_PRINT_OPERATIONS > 2)
1512    poly w = NULL; int wl = 0;
1513    printf("matrix after %d steps:\n", k - 1);
1514    for (int u = 0; u < k; u++)
1515    {
1516      for (int v = 0; v < k; v++)
1517      {
1518        if ((v < k - 1) && (u > v))
1519          wl = 0;
1520        else
1521        {
1522          w = tempMatrix[rowPermutation[u] * k + v];
1523          wl = pLength(w);
1524        }
1525        printf("%5d  ", wl);
1526      }
1527      printf("\n");
1528    }
1529#endif
1530    poly result = tempMatrix[rowPermutation[k - 1] * k + k - 1];
1531    if (sign == -1) result = pNeg(result);
1532    if (iSB != 0) result = kNF(iSB, currRing->qideal, result);
1533    PolyMinorValue mv(result, 0, 0, 0, 0, -1, -1);
1534    for (int i = 0; i < k * k; i++) pDelete(&tempMatrix[i]);
1535    omFreeSize(tempMatrix, k * k * sizeof(poly));
1536    delete[] rowPermutation;
1537    delete[] theColumns;
1538    delete[] theRows;
1539    return mv;
1540  }
1541}
1542
Note: See TracBrowser for help on using the repository browser.