source: git/Singular/MinorProcessor.cc @ d2ea299

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