source: git/Singular/MinorProcessor.cc @ 92d684

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