зеркало из https://github.com/mozilla/gecko-dev.git
340 строки
7.7 KiB
C++
340 строки
7.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "Fundamentals.h"
|
|
#include "FastBitMatrix.h"
|
|
#include "FastBitSet.h"
|
|
#include "Pool.h"
|
|
#include "prbit.h" // for PR_CEILING_LOG2
|
|
|
|
|
|
//
|
|
// Resize the matrix. Allocate the words from the given pool.
|
|
//
|
|
void FastBitMatrix::sizeTo(Pool& pool, Uint32 nRows, Uint32 nCols)
|
|
{
|
|
PR_ASSERT(nRows && nCols);
|
|
|
|
Uint32 rowSizeInWords = (nCols + 31) >> 5;
|
|
this->rowSizeInWords = rowSizeInWords;
|
|
Uint8 shift;
|
|
|
|
PR_CEILING_LOG2(shift, rowSizeInWords);
|
|
|
|
if (shift) // The biggest square matrix we can allocate is Matrix(0x7ffe0,0x7ffe0) (524256).
|
|
PR_ASSERT((nRows & ~((1 << (32 - shift)) - 1)) == 0); // Overflow should send a signal (or exception).
|
|
|
|
Uint32 newSizeInWords = nRows << shift;
|
|
if (newSizeInWords > sizeInWords) {
|
|
sizeInWords = newSizeInWords;
|
|
bits = new(pool) Uint32[sizeInWords];
|
|
}
|
|
rowShift = shift;
|
|
#ifdef DEBUG_LOG
|
|
this->nCols = nCols;
|
|
#endif /* DEBUG_LOG */
|
|
}
|
|
|
|
//
|
|
// And rows src1 & src2 to row dst
|
|
//
|
|
void FastBitMatrix::andRows(Uint32 src1, Uint32 src2, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* srcPtr1 = &bits[getRowOffset(src1)];
|
|
Uint32* srcPtr2 = &bits[getRowOffset(src2)];
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &dstPtr[rowSizeInWords];
|
|
|
|
while (dstPtr < limit)
|
|
*dstPtr++ = *srcPtr1++ & *srcPtr2++;
|
|
}
|
|
|
|
//
|
|
// And rows src1 & src2 to row dst
|
|
//
|
|
void FastBitMatrix::andRows(Uint32 src, const FastBitSet& x, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords && (rowSizeInWords == x.sizeInWords));
|
|
|
|
Uint32* srcPtr1 = &bits[getRowOffset(src)];
|
|
Uint32* srcPtr2 = x.bits;
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &srcPtr2[x.sizeInWords];
|
|
|
|
while (srcPtr2 < limit)
|
|
*dstPtr++ = *srcPtr1++ & *srcPtr2++;
|
|
}
|
|
|
|
//
|
|
// Or rows src1 & src2 to row dst
|
|
//
|
|
void FastBitMatrix::orRows(Uint32 src1, Uint32 src2, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* srcPtr1 = &bits[getRowOffset(src1)];
|
|
Uint32* srcPtr2 = &bits[getRowOffset(src2)];
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &dstPtr[rowSizeInWords];
|
|
|
|
while (dstPtr < limit)
|
|
*dstPtr++ = *srcPtr1++ | *srcPtr2++;
|
|
}
|
|
|
|
//
|
|
// Or rows src1 & src2 to row dst
|
|
//
|
|
void FastBitMatrix::orRows(Uint32 src, const FastBitSet& x, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords && (rowSizeInWords == x.sizeInWords));
|
|
|
|
Uint32* srcPtr1 = &bits[getRowOffset(src)];
|
|
Uint32* srcPtr2 = x.bits;
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &srcPtr2[x.sizeInWords];
|
|
|
|
while (srcPtr2 < limit)
|
|
*dstPtr++ = *srcPtr1++ | *srcPtr2++;
|
|
}
|
|
|
|
//
|
|
// Compare the rows x and y. Return true if they are equal.
|
|
//
|
|
bool FastBitMatrix::compareRows(Uint32 x, Uint32 y) const
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* ptr1 = &bits[getRowOffset(x)];
|
|
Uint32* ptr2 = &bits[getRowOffset(y)];
|
|
Uint32* limit = &ptr1[rowSizeInWords];
|
|
|
|
while (ptr1 < limit)
|
|
if (*ptr1++ != *ptr2++)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Copy the row src to the row dst.
|
|
//
|
|
void FastBitMatrix::copyRows(Uint32 src, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* srcPtr = &bits[getRowOffset(src)];
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &srcPtr[rowSizeInWords];
|
|
|
|
while (srcPtr < limit)
|
|
*dstPtr++ = *srcPtr++;
|
|
}
|
|
|
|
//
|
|
// Copy the bitset x to the row dst.
|
|
//
|
|
void FastBitMatrix::copyRows(const FastBitSet& x, Uint32 dst)
|
|
{
|
|
PR_ASSERT(sizeInWords && x.sizeInWords == rowSizeInWords);
|
|
|
|
Uint32* srcPtr = x.bits;
|
|
Uint32* dstPtr = &bits[getRowOffset(dst)];
|
|
Uint32* limit = &srcPtr[x.sizeInWords];
|
|
|
|
while (srcPtr < limit)
|
|
*dstPtr++ = *srcPtr++;
|
|
}
|
|
|
|
//
|
|
// Copy the row x to the bitset x.
|
|
//
|
|
void FastBitMatrix::copyRows(Uint32 src, FastBitSet& x)
|
|
{
|
|
PR_ASSERT(sizeInWords && x.sizeInWords == rowSizeInWords);
|
|
|
|
Uint32* srcPtr = &bits[getRowOffset(src)];
|
|
Uint32* dstPtr = x.bits;
|
|
Uint32* limit = &dstPtr[x.sizeInWords];
|
|
|
|
while (dstPtr < limit)
|
|
*dstPtr++ = *srcPtr++;
|
|
}
|
|
|
|
//
|
|
// Clear the row
|
|
//
|
|
void FastBitMatrix::clear(Uint32 row)
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* ptr = &bits[getRowOffset(row)];
|
|
Int32 count = rowSizeInWords - 1;
|
|
register Uint32 zeros = Uint32(0);
|
|
|
|
do
|
|
ptr[count] = zeros;
|
|
while(--count >= 0);
|
|
}
|
|
|
|
//
|
|
// Set the row
|
|
//
|
|
void FastBitMatrix::set(Uint32 row)
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
Uint32* ptr = &bits[getRowOffset(row)];
|
|
Int32 count = rowSizeInWords - 1;
|
|
register Uint32 ones = Uint32(~0);
|
|
|
|
do
|
|
ptr[count] = ones;
|
|
while(--count >= 0);
|
|
}
|
|
|
|
|
|
//
|
|
// Arithmetic operators.
|
|
//
|
|
|
|
#define FastBitMatrixOperation(x, op, val) \
|
|
PR_ASSERT(sizeInWords && sizeInWords == x.sizeInWords); \
|
|
Int32 nRows = (sizeInWords >> rowShift) - 1; \
|
|
do { \
|
|
Int32 count = rowSizeInWords - 1; \
|
|
Uint32* dst = &bits[getRowOffset(nRows)]; \
|
|
Uint32* src = &x.bits[x.getRowOffset(nRows)]; \
|
|
do { \
|
|
Uint32 word = src[count]; \
|
|
if (word != val) \
|
|
dst[count] op word; \
|
|
} while(--count >= 0); \
|
|
} while(--nRows >= 0);
|
|
|
|
FastBitMatrix& FastBitMatrix::operator |= (const FastBitMatrix& x)
|
|
{
|
|
FastBitMatrixOperation(x, |=, 0);
|
|
return *this;
|
|
}
|
|
|
|
FastBitMatrix& FastBitMatrix::operator &= (const FastBitMatrix& x)
|
|
{
|
|
FastBitMatrixOperation(x, &=, Uint32(~0));
|
|
return *this;
|
|
}
|
|
|
|
FastBitMatrix& FastBitMatrix::operator ^= (const FastBitMatrix& x)
|
|
{
|
|
FastBitMatrixOperation(x, ^=, 0);
|
|
return *this;
|
|
}
|
|
|
|
FastBitMatrix& FastBitMatrix::operator -= (const FastBitMatrix& x)
|
|
{
|
|
FastBitMatrixOperation(x, &= ~, 0);
|
|
return *this;
|
|
}
|
|
|
|
#undef FastBitMatrixOperation
|
|
|
|
//
|
|
// Return true if the 2 matrix are equals.
|
|
//
|
|
bool operator == (const FastBitMatrix& x, const FastBitMatrix& y)
|
|
{
|
|
Uint32 nRows = x.sizeInWords >> x.rowShift;
|
|
|
|
if ((y.sizeInWords >> y.rowShift) != nRows)
|
|
return false;
|
|
|
|
Uint32* ptr1 = x.bits;
|
|
Uint32* ptr2 = y.bits;
|
|
Uint32* limit = &ptr1[x.sizeInWords];
|
|
|
|
while (ptr1 < limit)
|
|
if (*ptr1++ != *ptr2++)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Copy the bits from the bitmatrix x.
|
|
//
|
|
FastBitMatrix& FastBitMatrix::operator = (const FastBitMatrix& x)
|
|
{
|
|
Uint32 nRows = x.sizeInWords >> x.rowShift;
|
|
|
|
PR_ASSERT((nRows == (sizeInWords >> rowShift)) && (rowSizeInWords == x.rowSizeInWords));
|
|
|
|
Uint32* src = x.bits;
|
|
Uint32* dst = bits;
|
|
Uint32* limit = &dst[sizeInWords];
|
|
|
|
while (dst < limit)
|
|
*dst++ = *src++;
|
|
|
|
rowSizeInWords = x.rowSizeInWords;
|
|
rowShift = x.rowShift;
|
|
|
|
return *this;
|
|
}
|
|
|
|
#ifdef DEBUG_LOG
|
|
//
|
|
// Print the matrix.
|
|
//
|
|
void FastBitMatrix::printPretty(FILE* f) const
|
|
{
|
|
PR_ASSERT(sizeInWords);
|
|
|
|
fprintf(f, "[\n");
|
|
Uint32 nRows = sizeInWords >> rowShift;
|
|
for (Uint32 i = 0; i < nRows; i++) {
|
|
fprintf(f, " ");
|
|
FastBitSet row(&bits[getRowOffset(i)], nCols);
|
|
row.printPretty(f);
|
|
}
|
|
fprintf(f, "]\n");
|
|
}
|
|
|
|
//
|
|
// Print the diffs.
|
|
//
|
|
void FastBitMatrix::printDiff(FILE *f, const FastBitMatrix& x) const
|
|
{
|
|
Uint32 nRows = sizeInWords >> rowShift;
|
|
PR_ASSERT((x.nCols == nCols) && (nRows == (x.sizeInWords >> x.rowShift)));
|
|
|
|
fprintf(f, "[\n");
|
|
for (Uint32 i = 0; i < nRows; i++) {
|
|
fprintf(f, " ");
|
|
FastBitSet row(&bits[i << rowShift], nCols);
|
|
FastBitSet xRow(&x.bits[i << rowShift], nCols);
|
|
row.printDiff(f, xRow);
|
|
}
|
|
fprintf(f, "]\n");
|
|
}
|
|
|
|
#endif /* DEBUG_LOG */
|