source: git/Singular/MinorProcessor.cc @ b38bc9

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