source: git/Singular/Minor.cc @ 16a86e

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