source: git/Singular/MinorProcessor.cc @ 7a81686

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