source: git/Singular/MinorProcessor.cc @ 643b538

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