source: git/Singular/Minor.cc @ e2afced

spielwiese
Last change on this file since e2afced was e2afced, checked in by Frank Seelisch <seelisch@…>, 15 years ago
changes due to 32bit vs. 64bit (to make code run on compute servers) git-svn-id: file:///usr/local/Singular/svn/trunk@12170 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 36.9 KB
Line 
1#include "mod2.h"
2
3#ifdef HAVE_MINOR
4
5#include "structs.h"
6#include "polys.h"
7#include <Minor.h>
8#include "febase.h"
9
10void MinorKey::reset() {
11    _numberOfRowBlocks = 0;
12    _numberOfColumnBlocks = 0;
13    delete [] _rowKey;
14    delete [] _columnKey;
15    _rowKey = 0;
16    _columnKey = 0;
17}
18
19MinorKey::MinorKey (const MinorKey& mk) {
20    _numberOfRowBlocks = mk.getNumberOfRowBlocks();
21    _numberOfColumnBlocks = mk.getNumberOfColumnBlocks();;
22
23    // allocate memory for new entries in _rowKey and _columnKey;
24    _rowKey = new unsigned int[_numberOfRowBlocks];
25    _columnKey = new unsigned int[_numberOfColumnBlocks];
26
27    // copying values from parameter arrays to private arrays
28    for (int r = 0; r < _numberOfRowBlocks; r++)
29        _rowKey[r] = mk.getRowKey(r);
30    for (int c = 0; c < _numberOfColumnBlocks; c++)
31        _columnKey[c] = mk.getColumnKey(c);
32}
33
34MinorKey& MinorKey::operator=(const MinorKey& mk) {
35    if (_numberOfRowBlocks != 0)    delete [] _rowKey;
36    if (_numberOfColumnBlocks != 0) delete [] _columnKey;
37    _numberOfRowBlocks = 0;
38    _numberOfColumnBlocks = 0;
39    _rowKey = 0;
40    _columnKey = 0;
41
42    _numberOfRowBlocks = mk.getNumberOfRowBlocks();
43    _numberOfColumnBlocks = mk.getNumberOfColumnBlocks();;
44
45    // allocate memory for new entries in _rowKey and _columnKey;
46    _rowKey = new unsigned int[_numberOfRowBlocks];
47    _columnKey = new unsigned int[_numberOfColumnBlocks];
48
49    // copying values from parameter arrays to private arrays
50    for (int r = 0; r < _numberOfRowBlocks; r++)
51        _rowKey[r] = mk.getRowKey(r);
52    for (int c = 0; c < _numberOfColumnBlocks; c++)
53        _columnKey[c] = mk.getColumnKey(c);
54       
55    return *this;
56}
57
58void MinorKey::set(const int lengthOfRowArray, const unsigned int* rowKey,
59                   const int lengthOfColumnArray, const unsigned int* columnKey) {
60    // free memory of _rowKey and _columnKey
61    if (_numberOfRowBlocks > 0) { delete [] _rowKey; }
62    if (_numberOfColumnBlocks > 0) { delete [] _columnKey; }
63
64    _numberOfRowBlocks = lengthOfRowArray;
65    _numberOfColumnBlocks = lengthOfColumnArray;
66
67    // allocate memory for new entries in _rowKey and _columnKey;
68    _rowKey = new unsigned int[_numberOfRowBlocks];
69    _columnKey = new unsigned int[_numberOfColumnBlocks];
70
71    // copying values from parameter arrays to private arrays
72    for (int r = 0; r < _numberOfRowBlocks; r++)
73        _rowKey[r] = rowKey[r];
74    for (int c = 0; c < _numberOfColumnBlocks; c++)
75        _columnKey[c] = columnKey[c];
76}
77
78MinorKey::MinorKey(const int lengthOfRowArray, const unsigned int* const rowKey,
79                   const int lengthOfColumnArray, const unsigned int* const columnKey) {
80    _numberOfRowBlocks = lengthOfRowArray;
81    _numberOfColumnBlocks = lengthOfColumnArray;
82
83    // allocate memory for new entries in _rowKey and _columnKey;
84    _rowKey = new unsigned int[_numberOfRowBlocks];
85    _columnKey = new unsigned int[_numberOfColumnBlocks];
86
87    // copying values from parameter arrays to private arrays
88    for (int r = 0; r < _numberOfRowBlocks; r++)
89        _rowKey[r] = rowKey[r];
90
91    for (int c = 0; c < _numberOfColumnBlocks; c++)
92        _columnKey[c] = columnKey[c];
93}
94
95MinorKey::~MinorKey() {
96    // free memory of _rowKey and _columnKey
97    delete [] _rowKey;
98    delete [] _columnKey;
99}
100
101void MinorKey::print() const {
102    cout << this->toString();
103}
104
105int MinorKey::getAbsoluteRowIndex(const int i) const {
106    // This method is to return the absolute (0-based) index of the i-th row encoded in \a this.
107    // Example: bit-pattern of rows: "10010001101", i = 3:
108    //    This should yield the 0-based absolute index of the 3-rd bit (counted from the right), i.e. 7.
109
110    int matchedBits = -1; // counter for matched bits; this needs to reach i, then we're done
111    for (int block = 0; block < getNumberOfRowBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
112        unsigned int blockBits = getRowKey(block); // the bits in this block of 32 bits
113        unsigned int shiftedBit = 1;
114        int exponent = 0;
115        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
116        while (exponent < 32) {
117            if (shiftedBit & blockBits) matchedBits++;
118            if (matchedBits == i) return exponent + (32 * block);
119            shiftedBit = shiftedBit << 1;
120            exponent++;
121        }
122    }
123    // We should never reach this line of code.
124    assert(false);
125}
126
127int MinorKey::getAbsoluteColumnIndex(const int i) const {
128    // This method is to return the absolute (0-based) index of the i-th column encoded in \a this.
129    // Example: bit-pattern of columns: "10010001101", i = 3:
130    //    This should yield the 0-based absolute index of the 3-rd bit (counted from the right), i.e. 7.
131
132    int matchedBits = -1; // counter for matched bits; this needs to reach i, then we're done
133    for (int block = 0; block < getNumberOfColumnBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
134        unsigned int blockBits = getColumnKey(block); // the bits in this block of 32 bits
135        unsigned int shiftedBit = 1;
136        int exponent = 0;
137        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
138        while (exponent < 32) {
139            if (shiftedBit & blockBits) matchedBits++;
140            if (matchedBits == i) return exponent + (32 * block);
141            shiftedBit = shiftedBit << 1;
142            exponent++;
143        }
144    }
145    // We should never reach this line of code.
146    assert(false);
147}
148
149void MinorKey::getAbsoluteRowIndices(int* const target) const {
150    int i = 0; // index for filling the target array
151    for (int block = 0; block < getNumberOfRowBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
152        unsigned int blockBits = getRowKey(block); // the bits in this block of 32 bits
153        unsigned int shiftedBit = 1;
154        int exponent = 0;
155        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
156        while (exponent < 32) {
157            if (shiftedBit & blockBits) target[i++] = exponent + (32 * block);
158            shiftedBit = shiftedBit << 1;
159            exponent++;
160        }
161    }
162    return;
163}
164
165void MinorKey::getAbsoluteColumnIndices(int* const target) const {
166    int i = 0; // index for filling the target array
167    for (int block = 0; block < getNumberOfColumnBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
168        unsigned int blockBits = getColumnKey(block); // the bits in this block of 32 bits
169        unsigned int shiftedBit = 1;
170        int exponent = 0;
171        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
172        while (exponent < 32) {
173            if (shiftedBit & blockBits) target[i++] = exponent + (32 * block);
174            shiftedBit = shiftedBit << 1;
175            exponent++;
176        }
177    }
178    return;
179}
180
181int MinorKey::getRelativeRowIndex(const int i) const {
182    // This method is to return the relative (0-based) index of the row with absolute index \c i.
183    // Example: bit-pattern of rows: "10010001101", i = 7:
184    //    This should yield the 0-based relative index of the bit corresponding to row no. 7,
185    //    i.e. 3.
186
187    int matchedBits = -1; // counter for matched bits; this is going to contain our return value
188    for (int block = 0; block < getNumberOfRowBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
189        unsigned int blockBits = getRowKey(block); // the bits in this block of 32 bits
190        unsigned int shiftedBit = 1;
191        int exponent = 0;
192        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
193        while (exponent < 32) {
194            if (shiftedBit & blockBits) matchedBits++;
195            if (exponent + (32 * block) == i) return matchedBits;
196            shiftedBit = shiftedBit << 1;
197            exponent++;
198        }
199    }
200    // We should never reach this line of code.
201    assert(false);
202}
203
204int MinorKey::getRelativeColumnIndex(const int i) const {
205    // This method is to return the relative (0-based) index of the column with absolute index \c i.
206    // Example: bit-pattern of columns: "10010001101", i = 7:
207    //    This should yield the 0-based relative index of the bit corresponding to column no. 7,
208    //    i.e. 3.
209
210    int matchedBits = -1; // counter for matched bits; this is going to contain our return value
211    for (int block = 0; block < getNumberOfColumnBlocks(); block ++) { // start with lowest bits, i.e. in block No. 0
212        unsigned int blockBits = getColumnKey(block); // the bits in this block of 32 bits
213        unsigned int shiftedBit = 1;
214        int exponent = 0;
215        // The invariant "shiftedBit = 2^exponent" will hold throughout the entire while loop.
216        while (exponent < 32) {
217            if (shiftedBit & blockBits) matchedBits++;
218            if (exponent + (32 * block) == i) return matchedBits;
219            shiftedBit = shiftedBit << 1;
220            exponent++;
221        }
222    }
223    // We should never reach this line of code.
224    assert(false);
225}
226
227unsigned int MinorKey::getRowKey(const int blockIndex) const {
228    return _rowKey[blockIndex];
229}
230
231unsigned int MinorKey::getColumnKey(const int blockIndex) const {
232    return _columnKey[blockIndex];
233}
234
235int MinorKey::getNumberOfRowBlocks() const {
236    return _numberOfRowBlocks;
237}
238
239int MinorKey::getNumberOfColumnBlocks() const {
240    return _numberOfColumnBlocks;
241}
242
243int MinorKey::getSetBits(const int a) const {
244    int b = 0;
245    if (a == 1) { // rows
246        for (int i = 0; i < _numberOfRowBlocks; i++) {
247            unsigned int m = _rowKey[i];
248            unsigned int k = 1;
249            for (int j = 0; j < 32; j++) {
250                // k = 2^j
251                if (m & k) b++;
252                k = k << 1;
253            }
254        }
255    }
256    else { // columns
257        for (int i = 0; i < _numberOfColumnBlocks; i++) {
258            unsigned int m = _columnKey[i];
259            unsigned int k = 1;
260            for (int j = 0; j < 32; j++) {
261                // k = 2^j
262                if (m & k) b++;
263                k = k << 1;
264            }
265        }
266    }
267    return b;
268}
269
270MinorKey MinorKey::getSubMinorKey (const int absoluteEraseRowIndex,
271                                   const int absoluteEraseColumnIndex) const {
272    int rowBlock = absoluteEraseRowIndex / 32;
273    int exponent = absoluteEraseRowIndex % 32;
274    unsigned int newRowBits = getRowKey(rowBlock) - (1 << exponent);
275    int highestRowBlock = getNumberOfRowBlocks() - 1;
276    // highestRowBlock will finally contain the highest block index with non-zero bit pattern
277    if ((newRowBits == 0) && (rowBlock == highestRowBlock)) {
278        // we have thus nullified the highest block;
279        // we can now forget about the highest block...
280        highestRowBlock -= 1;
281        while (getRowKey(highestRowBlock) == 0) // ...and maybe even some more zero-blocks
282            highestRowBlock -= 1;
283    }
284    // highestRowBlock now contains the highest row block index with non-zero bit pattern
285
286    int columnBlock = absoluteEraseColumnIndex / 32;
287    exponent = absoluteEraseColumnIndex % 32;
288    unsigned int newColumnBits = getColumnKey(columnBlock) - (1 << exponent);
289    int highestColumnBlock = getNumberOfColumnBlocks() - 1;
290    // highestColumnBlock will finally contain the highest block index with non-zero bit pattern
291    if ((newColumnBits == 0) && (columnBlock == highestColumnBlock)) {
292        // we have thus nullified the highest block;
293        // we can now forget about the highest block...
294        highestColumnBlock -= 1;
295        while (getColumnKey(highestColumnBlock) == 0) // ...and maybe even some more zero-blocks
296            highestColumnBlock -= 1;
297    }
298    // highestColumnBlock now contains the highest column block index with non-zero bit pattern
299
300    MinorKey result(highestRowBlock + 1, _rowKey, highestColumnBlock + 1, _columnKey);
301    // This is just a copy with maybe some leading bit blocks omitted. We still need to re-define
302    // the row block at index 'rowBlock' and the column block at index 'columnBlock':
303    if ((newRowBits != 0) || (rowBlock < getNumberOfRowBlocks() - 1)) result.setRowKey(rowBlock, newRowBits);
304    if ((newColumnBits != 0) || (columnBlock < getNumberOfColumnBlocks() - 1)) result.setColumnKey(columnBlock, newColumnBits);
305
306    if (result.getSetBits(1) != result.getSetBits(2)) { // asserts that the number of selected rows and columns are equal
307        cout << endl;
308        this->print();
309        cout << endl;
310        result.print();
311        cout << endl;
312        cout << "rows: " << result.getSetBits(1) << " / columns: " << result.getSetBits(2);
313        cout << endl;
314        cout << "row to be erased: " << absoluteEraseRowIndex << " / column to be erased: " << absoluteEraseColumnIndex << endl;
315        assert(false);
316    }
317
318    return result;
319}
320
321void MinorKey::setRowKey (const int blockIndex, const unsigned int rowKey) {
322    _rowKey[blockIndex] = rowKey;
323}
324
325void MinorKey::setColumnKey (const int blockIndex, const unsigned int columnKey) {
326    _columnKey[blockIndex] = columnKey;
327}
328
329int MinorKey::compare (const MinorKey& that) const {
330    // compare by rowKeys first; in case of equality, use columnKeys
331    if (this->getNumberOfRowBlocks() < that.getNumberOfRowBlocks())
332        return -1;
333    if (this->getNumberOfRowBlocks() > that.getNumberOfRowBlocks())
334        return 1;
335    // Here, numbers of rows are equal.
336    for (int r = this->getNumberOfRowBlocks() - 1; r >= 0; r--) {
337        if (this->getRowKey(r) < that.getRowKey(r)) return -1;
338        if (this->getRowKey(r) > that.getRowKey(r)) return 1;
339    }
340    // Here, this and that encode ecaxtly the same sets of rows.
341    // Now, we take a look at the columns.
342    if (this->getNumberOfColumnBlocks() < that.getNumberOfColumnBlocks())
343        return -1;
344    if (this->getNumberOfColumnBlocks() > that.getNumberOfColumnBlocks())
345        return 1;
346    // Here, numbers of columns are equal.
347    for (int c = this->getNumberOfColumnBlocks() - 1; c >= 0; c--) {
348        if (this->getColumnKey(c) < that.getColumnKey(c)) return -1;
349        if (this->getColumnKey(c) > that.getColumnKey(c)) return 1;
350    }
351    // Here, this and that encode exactly the same sets of rows and columns.
352    return 0;
353}
354
355// just to make the compiler happy;
356// this method should never be called
357bool MinorKey::operator==(const MinorKey& mk) const {
358    assert(false);
359    return this->compare(mk) == 0;
360}
361
362// just to make the compiler happy;
363// this method should never be called
364bool MinorKey::operator<(const MinorKey& mk) const {
365    assert(false);
366    return this->compare(mk) == -1;
367}
368
369void MinorKey::selectFirstRows (const int k, const MinorKey& mk) {
370    int hitBits = 0;      // the number of bits we have hit; in the end, this has to be equal to k,
371                          // the dimension of the minor
372    int blockIndex = -1;  // the index of the current int in mk
373    unsigned int highestInt = 0;  // the new highest block of this MinorKey
374    // We determine which ints of mk we can copy. Their indices will be 0, 1, ..., blockIndex - 1.
375    // And highestInt is going to capture the highest int (which may be only a portion of
376    // the corresponding int in mk. We loop until hitBits = k:
377    while (hitBits < k) {
378        blockIndex++;
379        highestInt = 0;
380        unsigned int currentInt = mk.getRowKey(blockIndex);
381        unsigned int shiftedBit = 1;
382        int exponent = 0;
383        // invariant in the loop: shiftedBit = 2^exponent
384        while (exponent < 32 && hitBits < k) {
385            if (shiftedBit & currentInt) {
386                highestInt += shiftedBit;
387                hitBits++;
388            }
389            shiftedBit = shiftedBit << 1;
390            exponent++;
391        }
392    }
393    // free old memory
394    delete [] _rowKey; _rowKey = 0;
395    _numberOfRowBlocks = blockIndex + 1;
396    // allocate memory for new entries in _rowKey;
397    _rowKey = new unsigned int[_numberOfRowBlocks];
398    // copying values from mk to this MinorKey
399    for (int r = 0; r < blockIndex; r++)
400        _rowKey[r] = mk.getRowKey(r);
401    _rowKey[blockIndex] = highestInt;
402}
403
404void MinorKey::selectFirstColumns (const int k, const MinorKey& mk) {
405    int hitBits = 0;      // the number of bits we have hit; in the end, this has to be equal to k,
406                          // the dimension of the minor
407    int blockIndex = -1;  // the index of the current int in mk
408    unsigned int highestInt = 0;  // the new highest block of this MinorKey
409    // We determine which ints of mk we can copy. Their indices will be 0, 1, ..., blockIndex - 1.
410    // And highestInt is going to capture the highest int (which may be only a portion of
411    // the corresponding int in mk. We loop until hitBits = k:
412    while (hitBits < k) {
413        blockIndex++;
414        highestInt = 0;
415        unsigned int currentInt = mk.getColumnKey(blockIndex);
416        unsigned int shiftedBit = 1;
417        int exponent = 0;
418        // invariant in the loop: shiftedBit = 2^exponent
419        while (exponent < 32 && hitBits < k) {
420            if (shiftedBit & currentInt) {
421                highestInt += shiftedBit;
422                hitBits++;
423            }
424            shiftedBit = shiftedBit << 1;
425            exponent++;
426        }
427    }
428    // free old memory
429    delete [] _columnKey; _columnKey = 0;
430    _numberOfColumnBlocks = blockIndex + 1;
431    // allocate memory for new entries in _columnKey;
432    _columnKey = new unsigned int[_numberOfColumnBlocks];
433    // copying values from mk to this MinorKey
434    for (int c = 0; c < blockIndex; c++)
435        _columnKey[c] = mk.getColumnKey(c);
436    _columnKey[blockIndex] = highestInt;
437}
438
439bool MinorKey::selectNextRows (const int k, const MinorKey& mk) {
440    // We need to compute the set of k rows which must all be contained in mk.
441    // AND: This set must be the least possible of this kind which is larger
442    //      than the currently encoded set of rows. (Here, '<' is w.r.t. to the natural
443    //       ordering on multi-indices.
444    // Example: mk encodes the rows according to the bit pattern 11010111, k = 3, this
445    //          MinorKey encodes 10010100. Then, the method must shift the set of rows in
446    //          this MinorKey to 11000001 (, and return true).
447
448    // The next two variables will finally name a row which is
449    // (1) currently not yet among the rows in this MinorKey, but
450    // (2) among the rows in mk, and
451    // (3) which is "higher" than the lowest row in this MinorKey, and
452    // (4) which is the lowest possible choice such that (1) - (3) hold.
453    // If we should not be able to find such a row, then there is no next subset of rows.
454    // In this case, the method will return false; otherwise always true.
455    int newBitBlockIndex = 0;         // the block index of the bit
456    unsigned int newBitToBeSet = 0;  // the bit as 2^e, where 0 <= e <= 31
457
458    int blockCount = this->getNumberOfRowBlocks();  // number of ints (representing rows) in this MinorKey
459    int mkBlockIndex = mk.getNumberOfRowBlocks();   // for iterating along the blocks of mk
460
461    int hitBits = 0;    // the number of bits we have hit
462    int bitCounter = 0; // for storing the number of bits hit before a specific moment; see below
463
464    while (hitBits < k) {
465        mkBlockIndex--;
466        unsigned int currentInt = mk.getRowKey(mkBlockIndex);
467        unsigned int shiftedBit = 1 << 31; // initially, this equals 2^31, i.e. the highest bit
468        while (hitBits < k && shiftedBit > 0) {
469            if ((blockCount - 1 >= mkBlockIndex) &&
470                (shiftedBit & this->getRowKey(mkBlockIndex))) hitBits++;
471            else if (shiftedBit & currentInt) {
472                newBitToBeSet = shiftedBit;
473                newBitBlockIndex = mkBlockIndex;
474                bitCounter = hitBits; // So, whenever we set newBitToBeSet, we want to remember the momentary
475                                      // number of hit bits. This will later be needed; see below.
476            }
477            shiftedBit = shiftedBit >> 1;
478        }
479    }
480
481    if (newBitToBeSet == 0) {
482        return false;
483    }
484    else {
485        // Note that the following must hold when reaching this line of code:
486        // (1) The row with bit newBitToBeSet in this->getRowKey(newBitBlockIndex) is currently
487        //     not among the rows in this MinorKey, but
488        // (2) it is among the rows in mk, and
489        // (3) it is higher than the lowest row in this MinorKey, and
490        // (4) it is the lowest possible choice such that (1) - (3) hold.
491        // In the above example, we would reach this line with
492        // newBitToBeSet == 2^6 and bitCounter == 1 (resulting from the bit 2^7).
493
494        if (blockCount - 1 < newBitBlockIndex) { // In this case, _rowKey is to small.
495            // free old memory
496            delete [] _rowKey; _rowKey = 0;
497            _numberOfRowBlocks = newBitBlockIndex + 1;
498            // allocate memory for new entries in _rowKey;
499            _rowKey = new unsigned int[_numberOfRowBlocks];
500        }
501        else {
502            // We need to delete all bits in _rowKey[newBitBlockIndex] that are below newBitToBeSet:
503            unsigned int anInt = this->getRowKey(newBitBlockIndex);
504            unsigned int deleteBit = newBitToBeSet >> 1; // in example: = 2^5
505            while (deleteBit > 0) {
506                if (anInt & deleteBit) anInt -= deleteBit;
507                deleteBit = deleteBit >> 1;
508            };
509            _rowKey[newBitBlockIndex] = anInt;
510            // ...and we delete all entries in _rowKey[i] for 0 <= i < newBitBlockIndex
511            for (int i = 0; i < newBitBlockIndex; i++)
512                _rowKey[i] = 0;
513        }
514
515        // We have now deleted all bits from _rowKey[...] below the bit 2^newBitToBeSet.
516        // In the example we shall have at this point: _rowKey[...] = 10000000.
517        // Now let's set the new bit:
518        _rowKey[newBitBlockIndex] += newBitToBeSet; // _rowKey[newBitBlockIndex] = 11000000
519        bitCounter++; // This is now the number of correct bits in _rowKey[...]; i.e. in the
520                      // example this will be equal to 2.
521
522        // Now we only need to fill _rowKey[...] with the lowest possible bits until it
523        // consists of exactly k bits. (We know that we need to set exactly (k - bitCounter)
524        // additional bits.)
525        mkBlockIndex = -1;
526        while (bitCounter < k) {
527            mkBlockIndex++;
528            unsigned int currentInt = mk.getRowKey(mkBlockIndex);
529            unsigned int shiftedBit = 1;
530            int exponent = 0;
531            // invariant: shiftedBit = 2^exponent
532            while (bitCounter < k && exponent < 32) {
533                if (shiftedBit & currentInt) {
534                    _rowKey[mkBlockIndex] += shiftedBit;
535                    bitCounter++;
536                };
537                shiftedBit = shiftedBit << 1;
538                exponent++;
539            }
540        };
541        // in the example, we shall obtain _rowKey[...] = 11000001
542
543        return true;
544    }
545}
546
547bool MinorKey::selectNextColumns (const int k, const MinorKey& mk) {
548    // We need to compute the set of k columns which must all be contained in mk.
549    // AND: This set must be the least possible of this kind which is larger
550    //      than the currently encoded set of columns. (Here, '<' is w.r.t. to the natural
551    //       ordering on multi-indices.
552    // Example: mk encodes the columns according to the bit pattern 11010111, k = 3, this
553    //          MinorKey encodes 10010100. Then, the method must shift the set of columns in
554    //          this MinorKey to 11000001 (, and return true).
555
556    // The next two variables will finally name a columns which is
557    // (1) currently not yet among the columns in this MinorKey, but
558    // (2) among the columns in mk, and
559    // (3) which is "higher" than the lowest columns in this MinorKey, and
560    // (4) which is the lowest possible choice such that (1) - (3) hold.
561    // If we should not be able to find such a columns, then there is no next subset of columns.
562    // In this case, the method will return false; otherwise always true.
563    int newBitBlockIndex = 0;         // the block index of the bit
564    unsigned int newBitToBeSet = 0;  // the bit as 2^e, where 0 <= e <= 31
565
566    int blockCount = this->getNumberOfColumnBlocks();  // number of ints (representing columns) in this MinorKey
567    int mkBlockIndex = mk.getNumberOfColumnBlocks();   // for iterating along the blocks of mk
568
569    int hitBits = 0;    // the number of bits we have hit
570    int bitCounter = 0; // for storing the number of bits hit before a specific moment; see below
571
572    while (hitBits < k) {
573        mkBlockIndex--;
574        unsigned int currentInt = mk.getColumnKey(mkBlockIndex);
575        unsigned int shiftedBit = 1 << 31; // initially, this equals 2^31, i.e. the highest bit
576        while (hitBits < k && shiftedBit > 0) {
577            if ((blockCount - 1 >= mkBlockIndex) &&
578                (shiftedBit & this->getColumnKey(mkBlockIndex))) hitBits++;
579            else if (shiftedBit & currentInt) {
580                newBitToBeSet = shiftedBit;
581                newBitBlockIndex = mkBlockIndex;
582                bitCounter = hitBits; // So, whenever we set newBitToBeSet, we want to remember the momentary
583                                      // number of hit bits. This will later be needed; see below.
584            }
585            shiftedBit = shiftedBit >> 1;
586        }                                           
587    }
588
589    if (newBitToBeSet == 0) {
590        return false;
591    }
592    else {
593        // Note that the following must hold when reaching this line of code:
594        // (1) The columns with bit newBitToBeSet in this->getColumnKey(newBitBlockIndex) is currently
595        //     not among the columns in this MinorKey, but
596        // (2) it is among the columns in mk, and
597        // (3) it is higher than the lowest columns in this MinorKey, and
598        // (4) it is the lowest possible choice such that (1) - (3) hold.
599        // In the above example, we would reach this line with
600        // newBitToBeSet == 2^6 and bitCounter == 1 (resulting from the bit 2^7).
601
602        if (blockCount - 1 < newBitBlockIndex) { // In this case, _columnKey is to small.
603            // free old memory
604            delete [] _columnKey; _columnKey = 0;
605            _numberOfColumnBlocks = newBitBlockIndex + 1;
606            // allocate memory for new entries in _columnKey;
607            _columnKey = new unsigned int[_numberOfColumnBlocks];
608        }
609        else {
610            // We need to delete all bits in _columnKey[newBitBlockIndex] that are below newBitToBeSet:
611            unsigned int anInt = this->getColumnKey(newBitBlockIndex);
612            unsigned int deleteBit = newBitToBeSet >> 1; // in example: = 2^5
613            while (deleteBit > 0) {
614                if (anInt & deleteBit) anInt -= deleteBit;
615                deleteBit = deleteBit >> 1;
616            };
617            _columnKey[newBitBlockIndex] = anInt;
618            // ...and we delete all entries in _columnKey[i] for 0 <= i < newBitBlockIndex
619            for (int i = 0; i < newBitBlockIndex; i++)
620                _columnKey[i] = 0;
621        }
622
623        // We have now deleted all bits from _columnKey[...] below the bit 2^newBitToBeSet.
624        // In the example we shall have at this point: _columnKey[...] = 10000000.
625        // Now let's set the new bit:
626        _columnKey[newBitBlockIndex] += newBitToBeSet; // _columnKey[newBitBlockIndex] = 11000000
627        bitCounter++; // This is now the number of correct bits in _columnKey[...]; i.e. in the
628                      // example this will be equal to 2.
629
630        // Now we only need to fill _columnKey[...] with the lowest possible bits until it
631        // consists of exactly k bits. (We know that we need to set exactly (k - bitCounter)
632        // additional bits.)
633        mkBlockIndex = -1;
634        while (bitCounter < k) {
635            mkBlockIndex++;
636            unsigned int currentInt = mk.getColumnKey(mkBlockIndex);
637            unsigned int shiftedBit = 1;
638            int exponent = 0;
639            // invariant: shiftedBit = 2^exponent
640            while (bitCounter < k && exponent < 32) {
641                if (shiftedBit & currentInt) {
642                    _columnKey[mkBlockIndex] += shiftedBit;
643                    bitCounter++;
644                };
645                shiftedBit = shiftedBit << 1;
646                exponent++;
647            }
648        };
649        // in the example, we shall obtain _columnKey[...] = 11000001
650
651        return true;
652    }
653}
654
655string MinorKey::toString() const {
656    char h[32];
657    string t = "";
658    string s = "(";
659    for (int r = this->getNumberOfRowBlocks() - 1; r >= 0; r--) {
660        sprintf(h, "%du", this->getRowKey(r)); t += h;
661        if (r < this->getNumberOfRowBlocks() - 1)
662            t = string(32 - t.length(), '0') + t;
663        s += t;
664    }
665    s += ", ";
666    for (int c = this->getNumberOfColumnBlocks() - 1; c >= 0; c--) {
667        sprintf(h, "%du", this->getColumnKey(c)); t += h;
668        if (c < this->getNumberOfColumnBlocks() - 1)
669            t = string(32 - t.length(), '0') + t;
670        s += t;
671    }
672    s += ")";
673    return s;
674}
675
676int MinorValue::_RankingStrategy = -1;
677
678int MinorValue::getWeight () const
679{
680  assert(false);  // must be overridden in derived classes
681  return 0;
682}
683
684// just to make the compiler happy;
685// this method should never be called
686bool MinorValue::operator==(const MinorValue& mv) const {
687    assert(false);
688    return (this == &mv);  // compare addresses of both objects
689}
690
691string MinorValue::toString () const
692{
693  assert(false);  // must be overridden in derived classes
694  return "";
695}
696
697// just to make the compiler happy;
698// this method should never be called
699bool MinorValue::operator<(const MinorValue& mv) const {
700    assert(false);
701    return (this < &mv);  // compare addresses of both objects
702}
703
704int MinorValue::getRetrievals() const {
705    return _retrievals;
706}
707
708void MinorValue::incrementRetrievals() {
709    _retrievals++;
710}
711
712int MinorValue::getPotentialRetrievals() const {
713    return _potentialRetrievals;
714}
715
716int MinorValue::getMultiplications() const {
717    return _multiplications;
718}
719
720int MinorValue::getAdditions() const {
721    return _additions;
722}
723
724int MinorValue::getAccumulatedMultiplications() const {
725    return _accumulatedMult;
726}
727
728int MinorValue::getAccumulatedAdditions() const {
729    return _accumulatedSum;
730}
731
732void MinorValue::print() const {
733    cout << this->toString();
734}
735
736
737void MinorValue::SetRankingStrategy(const int rankingStrategy) {
738    _RankingStrategy = rankingStrategy;
739    if (_RankingStrategy == 6) {
740        // initialize the random generator with system time
741        srand ( time(NULL) );
742    }
743}
744
745int MinorValue::GetRankingStrategy() {
746    return _RankingStrategy;
747}
748
749// this is for generically accessing the rank measure regardless of
750// which strategy has been set
751int MinorValue::getUtility () const {
752    switch (this->GetRankingStrategy()) {
753        case 1: return this->rankMeasure1();
754        case 2: return this->rankMeasure2();
755        case 3: return this->rankMeasure3();
756        case 4: return this->rankMeasure4();
757        case 5: return this->rankMeasure5();
758        default: return this->rankMeasure1();
759    }
760}
761
762// here are some sensible caching strategies:
763int MinorValue::rankMeasure1 () const {
764    // number of actually performed multiplications
765    return this->getMultiplications();
766}
767
768int MinorValue::rankMeasure2 () const {
769    // accumulated number of performed multiplications, i.e. all including nested multiplications
770    return this->getAccumulatedMultiplications();
771}
772
773int MinorValue::rankMeasure3 () const {
774    // number of performed multiplications, weighted with the ratio of
775    // not yet performed retrievals over the maximal number of retrievals
776    return this->getMultiplications() * (this->getPotentialRetrievals() - this->getRetrievals())
777           / this->getPotentialRetrievals();
778}
779
780int MinorValue::rankMeasure4 () const {
781    // number of performed multiplications,
782    // multiplied with the number of not yet performed retrievals
783    return this->getMultiplications() * (this->getPotentialRetrievals() - this->getRetrievals());
784}
785
786int MinorValue::rankMeasure5 () const {
787    // number of not yet performed retrievals;
788    // tends to cache entries longer when they are going to be retrieved more often in the future
789    return this->getPotentialRetrievals() - this->getRetrievals();
790}
791
792int IntMinorValue::getWeight () const {
793    // put measure for size of MinorValue here, i.e. number of monomials in polynomial;
794    // so far, we use the accumulated number of multiplications (i.e., including all nested ones)
795    // to simmulate the size of a polynomial
796    return _accumulatedMult;
797}
798
799IntMinorValue::IntMinorValue (const int result, const int multiplications, const int additions,
800                                const int accumulatedMultiplications, const int accumulatedAdditions,
801                                const int retrievals, const int potentialRetrievals) {
802    _result = result;
803    _multiplications = multiplications;
804    _additions = additions;
805    _accumulatedMult = accumulatedMultiplications;
806    _accumulatedSum = accumulatedAdditions;
807    _potentialRetrievals = potentialRetrievals;
808    _retrievals = retrievals;
809}
810
811IntMinorValue::IntMinorValue () {
812    _result = -1;
813    _multiplications = -1;
814    _additions = -1;
815    _accumulatedMult = -1;
816    _accumulatedSum = -1;
817    _potentialRetrievals = -1;
818    _retrievals = -1;
819}
820
821IntMinorValue::~IntMinorValue()
822{
823}
824
825int IntMinorValue::getResult() const {
826    return _result;
827}
828
829string IntMinorValue::toString () const {
830    char h[10];
831
832    // Let's see whether a cache has been used to compute this MinorValue:
833    bool cacheHasBeenUsed = true;
834    if (this->getRetrievals() == -1) cacheHasBeenUsed = false;
835
836    sprintf(h, "%d", this->getResult());
837    string s = h;
838    s += " [retrievals: ";
839    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getRetrievals()); s += h; }
840    else s += "/";
841    s += " (of ";
842    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getPotentialRetrievals()); s += h; }
843    else s += "/";
844    s += "), *: ";
845    sprintf(h, "%d", this->getMultiplications()); s += h;
846    s += " (accumulated: ";
847    sprintf(h, "%d", this->getAccumulatedMultiplications()); s += h;
848    s += "), +: ";
849    sprintf(h, "%d", this->getAdditions()); s += h;
850    s += " (accumulated: ";
851    sprintf(h, "%d", this->getAccumulatedAdditions()); s += h;
852    s += "), rank: ";
853    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getUtility()); s += h; }
854    else s += "/";
855    s += "]";
856    return s;
857}
858
859IntMinorValue::IntMinorValue (const IntMinorValue& mv) {
860    _result = mv.getResult();
861    _retrievals = mv.getRetrievals();
862    _potentialRetrievals = mv.getPotentialRetrievals();
863    _multiplications = mv.getMultiplications();
864    _additions = mv.getAdditions();
865    _accumulatedMult = mv.getAccumulatedMultiplications();
866    _accumulatedSum = mv.getAccumulatedAdditions();
867}
868
869PolyMinorValue::PolyMinorValue (const poly result, const int multiplications, const int additions,
870                                const int accumulatedMultiplications, const int accumulatedAdditions,
871                                const int retrievals, const int potentialRetrievals) {
872    _result = pCopy(result);
873    // std::cout << std::endl << "PolyMinorValue creator, " << pString(_result);
874    _multiplications = multiplications;
875    _additions = additions;
876    _accumulatedMult = accumulatedMultiplications;
877    _accumulatedSum = accumulatedAdditions;
878    _potentialRetrievals = potentialRetrievals;
879    _retrievals = retrievals;
880}
881
882PolyMinorValue::PolyMinorValue () {
883    _result = pISet(0);
884    // std::cout << std::endl << "PolyMinorValue creator, " << pString(_result) << " STANDARD!";
885    _multiplications = -1;
886    _additions = -1;
887    _accumulatedMult = -1;
888    _accumulatedSum = -1;
889    _potentialRetrievals = -1;
890    _retrievals = -1;
891}
892
893PolyMinorValue::~PolyMinorValue()
894{
895  // p_Delete(&_result, currRing);
896}
897
898poly PolyMinorValue::getResult() const {
899    return _result;
900}
901
902int PolyMinorValue::getWeight () const {
903    // put measure for size of PolyMinorValue here, e.g. the number of monomials
904    // the cached polynomial
905    return pLength(_result); // the number of monomials in the polynomial
906}
907
908string PolyMinorValue::toString () const {
909    char h[10];
910
911    // Let's see whether a cache has been used to compute this MinorValue:
912    bool cacheHasBeenUsed = true;
913    if (this->getRetrievals() == -1) cacheHasBeenUsed = false;
914
915    string s = pString(_result);
916    s += " [retrievals: ";
917    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getRetrievals()); s += h; }
918    else s += "/";
919    s += " (of ";
920    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getPotentialRetrievals()); s += h; }
921    else s += "/";
922    s += "), *: ";
923    sprintf(h, "%d", this->getMultiplications()); s += h;
924    s += " (accumulated: ";
925    sprintf(h, "%d", this->getAccumulatedMultiplications()); s += h;
926    s += "), +: ";
927    sprintf(h, "%d", this->getAdditions()); s += h;
928    s += " (accumulated: ";
929    sprintf(h, "%d", this->getAccumulatedAdditions()); s += h;
930    s += "), rank: ";
931    if (cacheHasBeenUsed) { sprintf(h, "%d", this->getUtility()); s += h; }
932    else s += "/";
933    s += "]";
934    return s;
935}
936
937PolyMinorValue::PolyMinorValue (const PolyMinorValue& mv) {
938    _result = mv.getResult();
939    _retrievals = mv.getRetrievals();
940    _potentialRetrievals = mv.getPotentialRetrievals();
941    _multiplications = mv.getMultiplications();
942    _additions = mv.getAdditions();
943    _accumulatedMult = mv.getAccumulatedMultiplications();
944    _accumulatedSum = mv.getAccumulatedAdditions();
945}
946
947#endif // HAVE_MINOR
Note: See TracBrowser for help on using the repository browser.