1388 lines
43 KiB
C++
1388 lines
43 KiB
C++
|
|
#include "normBitmask.h"
|
|
#include "debug.h"
|
|
#include "sysdefs.h"
|
|
|
|
|
|
// Hamming weights for given one-byte bit masks
|
|
static unsigned char WEIGHT[256] =
|
|
{
|
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
|
};
|
|
|
|
// Bit location vectors for given one-byte bit masks
|
|
static unsigned char BITLOCS[256][8] =
|
|
{
|
|
{0, 0, 0, 0, 0, 0, 0, 0}, {7, 0, 0, 0, 0, 0, 0, 0},
|
|
{6, 0, 0, 0, 0, 0, 0, 0}, {6, 7, 0, 0, 0, 0, 0, 0},
|
|
{5, 0, 0, 0, 0, 0, 0, 0}, {5, 7, 0, 0, 0, 0, 0, 0},
|
|
{5, 6, 0, 0, 0, 0, 0, 0}, {5, 6, 7, 0, 0, 0, 0, 0},
|
|
{4, 0, 0, 0, 0, 0, 0, 0}, {4, 7, 0, 0, 0, 0, 0, 0},
|
|
{4, 6, 0, 0, 0, 0, 0, 0}, {4, 6, 7, 0, 0, 0, 0, 0},
|
|
{4, 5, 0, 0, 0, 0, 0, 0}, {4, 5, 7, 0, 0, 0, 0, 0},
|
|
{4, 5, 6, 0, 0, 0, 0, 0}, {4, 5, 6, 7, 0, 0, 0, 0},
|
|
{3, 0, 0, 0, 0, 0, 0, 0}, {3, 7, 0, 0, 0, 0, 0, 0},
|
|
{3, 6, 0, 0, 0, 0, 0, 0}, {3, 6, 7, 0, 0, 0, 0, 0},
|
|
{3, 5, 0, 0, 0, 0, 0, 0}, {3, 5, 7, 0, 0, 0, 0, 0},
|
|
{3, 5, 6, 0, 0, 0, 0, 0}, {3, 5, 6, 7, 0, 0, 0, 0},
|
|
{3, 4, 0, 0, 0, 0, 0, 0}, {3, 4, 7, 0, 0, 0, 0, 0},
|
|
{3, 4, 6, 0, 0, 0, 0, 0}, {3, 4, 6, 7, 0, 0, 0, 0},
|
|
{3, 4, 5, 0, 0, 0, 0, 0}, {3, 4, 5, 7, 0, 0, 0, 0},
|
|
{3, 4, 5, 6, 0, 0, 0, 0}, {3, 4, 5, 6, 7, 0, 0, 0},
|
|
{2, 0, 0, 0, 0, 0, 0, 0}, {2, 7, 0, 0, 0, 0, 0, 0},
|
|
{2, 6, 0, 0, 0, 0, 0, 0}, {2, 6, 7, 0, 0, 0, 0, 0},
|
|
{2, 5, 0, 0, 0, 0, 0, 0}, {2, 5, 7, 0, 0, 0, 0, 0},
|
|
{2, 5, 6, 0, 0, 0, 0, 0}, {2, 5, 6, 7, 0, 0, 0, 0},
|
|
{2, 4, 0, 0, 0, 0, 0, 0}, {2, 4, 7, 0, 0, 0, 0, 0},
|
|
{2, 4, 6, 0, 0, 0, 0, 0}, {2, 4, 6, 7, 0, 0, 0, 0},
|
|
{2, 4, 5, 0, 0, 0, 0, 0}, {2, 4, 5, 7, 0, 0, 0, 0},
|
|
{2, 4, 5, 6, 0, 0, 0, 0}, {2, 4, 5, 6, 7, 0, 0, 0},
|
|
{2, 3, 0, 0, 0, 0, 0, 0}, {2, 3, 7, 0, 0, 0, 0, 0},
|
|
{2, 3, 6, 0, 0, 0, 0, 0}, {2, 3, 6, 7, 0, 0, 0, 0},
|
|
{2, 3, 5, 0, 0, 0, 0, 0}, {2, 3, 5, 7, 0, 0, 0, 0},
|
|
{2, 3, 5, 6, 0, 0, 0, 0}, {2, 3, 5, 6, 7, 0, 0, 0},
|
|
{2, 3, 4, 0, 0, 0, 0, 0}, {2, 3, 4, 7, 0, 0, 0, 0},
|
|
{2, 3, 4, 6, 0, 0, 0, 0}, {2, 3, 4, 6, 7, 0, 0, 0},
|
|
{2, 3, 4, 5, 0, 0, 0, 0}, {2, 3, 4, 5, 7, 0, 0, 0},
|
|
{2, 3, 4, 5, 6, 0, 0, 0}, {2, 3, 4, 5, 6, 7, 0, 0},
|
|
{1, 0, 0, 0, 0, 0, 0, 0}, {1, 7, 0, 0, 0, 0, 0, 0},
|
|
{1, 6, 0, 0, 0, 0, 0, 0}, {1, 6, 7, 0, 0, 0, 0, 0},
|
|
{1, 5, 0, 0, 0, 0, 0, 0}, {1, 5, 7, 0, 0, 0, 0, 0},
|
|
{1, 5, 6, 0, 0, 0, 0, 0}, {1, 5, 6, 7, 0, 0, 0, 0},
|
|
{1, 4, 0, 0, 0, 0, 0, 0}, {1, 4, 7, 0, 0, 0, 0, 0},
|
|
{1, 4, 6, 0, 0, 0, 0, 0}, {1, 4, 6, 7, 0, 0, 0, 0},
|
|
{1, 4, 5, 0, 0, 0, 0, 0}, {1, 4, 5, 7, 0, 0, 0, 0},
|
|
{1, 4, 5, 6, 0, 0, 0, 0}, {1, 4, 5, 6, 7, 0, 0, 0},
|
|
{1, 3, 0, 0, 0, 0, 0, 0}, {1, 3, 7, 0, 0, 0, 0, 0},
|
|
{1, 3, 6, 0, 0, 0, 0, 0}, {1, 3, 6, 7, 0, 0, 0, 0},
|
|
{1, 3, 5, 0, 0, 0, 0, 0}, {1, 3, 5, 7, 0, 0, 0, 0},
|
|
{1, 3, 5, 6, 0, 0, 0, 0}, {1, 3, 5, 6, 7, 0, 0, 0},
|
|
{1, 3, 4, 0, 0, 0, 0, 0}, {1, 3, 4, 7, 0, 0, 0, 0},
|
|
{1, 3, 4, 6, 0, 0, 0, 0}, {1, 3, 4, 6, 7, 0, 0, 0},
|
|
{1, 3, 4, 5, 0, 0, 0, 0}, {1, 3, 4, 5, 7, 0, 0, 0},
|
|
{1, 3, 4, 5, 6, 0, 0, 0}, {1, 3, 4, 5, 6, 7, 0, 0},
|
|
{1, 2, 0, 0, 0, 0, 0, 0}, {1, 2, 7, 0, 0, 0, 0, 0},
|
|
{1, 2, 6, 0, 0, 0, 0, 0}, {1, 2, 6, 7, 0, 0, 0, 0},
|
|
{1, 2, 5, 0, 0, 0, 0, 0}, {1, 2, 5, 7, 0, 0, 0, 0},
|
|
{1, 2, 5, 6, 0, 0, 0, 0}, {1, 2, 5, 6, 7, 0, 0, 0},
|
|
{1, 2, 4, 0, 0, 0, 0, 0}, {1, 2, 4, 7, 0, 0, 0, 0},
|
|
{1, 2, 4, 6, 0, 0, 0, 0}, {1, 2, 4, 6, 7, 0, 0, 0},
|
|
{1, 2, 4, 5, 0, 0, 0, 0}, {1, 2, 4, 5, 7, 0, 0, 0},
|
|
{1, 2, 4, 5, 6, 0, 0, 0}, {1, 2, 4, 5, 6, 7, 0, 0},
|
|
{1, 2, 3, 0, 0, 0, 0, 0}, {1, 2, 3, 7, 0, 0, 0, 0},
|
|
{1, 2, 3, 6, 0, 0, 0, 0}, {1, 2, 3, 6, 7, 0, 0, 0},
|
|
{1, 2, 3, 5, 0, 0, 0, 0}, {1, 2, 3, 5, 7, 0, 0, 0},
|
|
{1, 2, 3, 5, 6, 0, 0, 0}, {1, 2, 3, 5, 6, 7, 0, 0},
|
|
{1, 2, 3, 4, 0, 0, 0, 0}, {1, 2, 3, 4, 7, 0, 0, 0},
|
|
{1, 2, 3, 4, 6, 0, 0, 0}, {1, 2, 3, 4, 6, 7, 0, 0},
|
|
{1, 2, 3, 4, 5, 0, 0, 0}, {1, 2, 3, 4, 5, 7, 0, 0},
|
|
{1, 2, 3, 4, 5, 6, 0, 0}, {1, 2, 3, 4, 5, 6, 7, 0},
|
|
{0, 0, 0, 0, 0, 0, 0, 0}, {0, 7, 0, 0, 0, 0, 0, 0},
|
|
{0, 6, 0, 0, 0, 0, 0, 0}, {0, 6, 7, 0, 0, 0, 0, 0},
|
|
{0, 5, 0, 0, 0, 0, 0, 0}, {0, 5, 7, 0, 0, 0, 0, 0},
|
|
{0, 5, 6, 0, 0, 0, 0, 0}, {0, 5, 6, 7, 0, 0, 0, 0},
|
|
{0, 4, 0, 0, 0, 0, 0, 0}, {0, 4, 7, 0, 0, 0, 0, 0},
|
|
{0, 4, 6, 0, 0, 0, 0, 0}, {0, 4, 6, 7, 0, 0, 0, 0},
|
|
{0, 4, 5, 0, 0, 0, 0, 0}, {0, 4, 5, 7, 0, 0, 0, 0},
|
|
{0, 4, 5, 6, 0, 0, 0, 0}, {0, 4, 5, 6, 7, 0, 0, 0},
|
|
{0, 3, 0, 0, 0, 0, 0, 0}, {0, 3, 7, 0, 0, 0, 0, 0},
|
|
{0, 3, 6, 0, 0, 0, 0, 0}, {0, 3, 6, 7, 0, 0, 0, 0},
|
|
{0, 3, 5, 0, 0, 0, 0, 0}, {0, 3, 5, 7, 0, 0, 0, 0},
|
|
{0, 3, 5, 6, 0, 0, 0, 0}, {0, 3, 5, 6, 7, 0, 0, 0},
|
|
{0, 3, 4, 0, 0, 0, 0, 0}, {0, 3, 4, 7, 0, 0, 0, 0},
|
|
{0, 3, 4, 6, 0, 0, 0, 0}, {0, 3, 4, 6, 7, 0, 0, 0},
|
|
{0, 3, 4, 5, 0, 0, 0, 0}, {0, 3, 4, 5, 7, 0, 0, 0},
|
|
{0, 3, 4, 5, 6, 0, 0, 0}, {0, 3, 4, 5, 6, 7, 0, 0},
|
|
{0, 2, 0, 0, 0, 0, 0, 0}, {0, 2, 7, 0, 0, 0, 0, 0},
|
|
{0, 2, 6, 0, 0, 0, 0, 0}, {0, 2, 6, 7, 0, 0, 0, 0},
|
|
{0, 2, 5, 0, 0, 0, 0, 0}, {0, 2, 5, 7, 0, 0, 0, 0},
|
|
{0, 2, 5, 6, 0, 0, 0, 0}, {0, 2, 5, 6, 7, 0, 0, 0},
|
|
{0, 2, 4, 0, 0, 0, 0, 0}, {0, 2, 4, 7, 0, 0, 0, 0},
|
|
{0, 2, 4, 6, 0, 0, 0, 0}, {0, 2, 4, 6, 7, 0, 0, 0},
|
|
{0, 2, 4, 5, 0, 0, 0, 0}, {0, 2, 4, 5, 7, 0, 0, 0},
|
|
{0, 2, 4, 5, 6, 0, 0, 0}, {0, 2, 4, 5, 6, 7, 0, 0},
|
|
{0, 2, 3, 0, 0, 0, 0, 0}, {0, 2, 3, 7, 0, 0, 0, 0},
|
|
{0, 2, 3, 6, 0, 0, 0, 0}, {0, 2, 3, 6, 7, 0, 0, 0},
|
|
{0, 2, 3, 5, 0, 0, 0, 0}, {0, 2, 3, 5, 7, 0, 0, 0},
|
|
{0, 2, 3, 5, 6, 0, 0, 0}, {0, 2, 3, 5, 6, 7, 0, 0},
|
|
{0, 2, 3, 4, 0, 0, 0, 0}, {0, 2, 3, 4, 7, 0, 0, 0},
|
|
{0, 2, 3, 4, 6, 0, 0, 0}, {0, 2, 3, 4, 6, 7, 0, 0},
|
|
{0, 2, 3, 4, 5, 0, 0, 0}, {0, 2, 3, 4, 5, 7, 0, 0},
|
|
{0, 2, 3, 4, 5, 6, 0, 0}, {0, 2, 3, 4, 5, 6, 7, 0},
|
|
{0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 7, 0, 0, 0, 0, 0},
|
|
{0, 1, 6, 0, 0, 0, 0, 0}, {0, 1, 6, 7, 0, 0, 0, 0},
|
|
{0, 1, 5, 0, 0, 0, 0, 0}, {0, 1, 5, 7, 0, 0, 0, 0},
|
|
{0, 1, 5, 6, 0, 0, 0, 0}, {0, 1, 5, 6, 7, 0, 0, 0},
|
|
{0, 1, 4, 0, 0, 0, 0, 0}, {0, 1, 4, 7, 0, 0, 0, 0},
|
|
{0, 1, 4, 6, 0, 0, 0, 0}, {0, 1, 4, 6, 7, 0, 0, 0},
|
|
{0, 1, 4, 5, 0, 0, 0, 0}, {0, 1, 4, 5, 7, 0, 0, 0},
|
|
{0, 1, 4, 5, 6, 0, 0, 0}, {0, 1, 4, 5, 6, 7, 0, 0},
|
|
{0, 1, 3, 0, 0, 0, 0, 0}, {0, 1, 3, 7, 0, 0, 0, 0},
|
|
{0, 1, 3, 6, 0, 0, 0, 0}, {0, 1, 3, 6, 7, 0, 0, 0},
|
|
{0, 1, 3, 5, 0, 0, 0, 0}, {0, 1, 3, 5, 7, 0, 0, 0},
|
|
{0, 1, 3, 5, 6, 0, 0, 0}, {0, 1, 3, 5, 6, 7, 0, 0},
|
|
{0, 1, 3, 4, 0, 0, 0, 0}, {0, 1, 3, 4, 7, 0, 0, 0},
|
|
{0, 1, 3, 4, 6, 0, 0, 0}, {0, 1, 3, 4, 6, 7, 0, 0},
|
|
{0, 1, 3, 4, 5, 0, 0, 0}, {0, 1, 3, 4, 5, 7, 0, 0},
|
|
{0, 1, 3, 4, 5, 6, 0, 0}, {0, 1, 3, 4, 5, 6, 7, 0},
|
|
{0, 1, 2, 0, 0, 0, 0, 0}, {0, 1, 2, 7, 0, 0, 0, 0},
|
|
{0, 1, 2, 6, 0, 0, 0, 0}, {0, 1, 2, 6, 7, 0, 0, 0},
|
|
{0, 1, 2, 5, 0, 0, 0, 0}, {0, 1, 2, 5, 7, 0, 0, 0},
|
|
{0, 1, 2, 5, 6, 0, 0, 0}, {0, 1, 2, 5, 6, 7, 0, 0},
|
|
{0, 1, 2, 4, 0, 0, 0, 0}, {0, 1, 2, 4, 7, 0, 0, 0},
|
|
{0, 1, 2, 4, 6, 0, 0, 0}, {0, 1, 2, 4, 6, 7, 0, 0},
|
|
{0, 1, 2, 4, 5, 0, 0, 0}, {0, 1, 2, 4, 5, 7, 0, 0},
|
|
{0, 1, 2, 4, 5, 6, 0, 0}, {0, 1, 2, 4, 5, 6, 7, 0},
|
|
{0, 1, 2, 3, 0, 0, 0, 0}, {0, 1, 2, 3, 7, 0, 0, 0},
|
|
{0, 1, 2, 3, 6, 0, 0, 0}, {0, 1, 2, 3, 6, 7, 0, 0},
|
|
{0, 1, 2, 3, 5, 0, 0, 0}, {0, 1, 2, 3, 5, 7, 0, 0},
|
|
{0, 1, 2, 3, 5, 6, 0, 0}, {0, 1, 2, 3, 5, 6, 7, 0},
|
|
{0, 1, 2, 3, 4, 0, 0, 0}, {0, 1, 2, 3, 4, 7, 0, 0},
|
|
{0, 1, 2, 3, 4, 6, 0, 0}, {0, 1, 2, 3, 4, 6, 7, 0},
|
|
{0, 1, 2, 3, 4, 5, 0, 0}, {0, 1, 2, 3, 4, 5, 7, 0},
|
|
{0, 1, 2, 3, 4, 5, 6, 0}, {0, 1, 2, 3, 4, 5, 6, 7}
|
|
};
|
|
|
|
NormBitmask::NormBitmask()
|
|
: mask(NULL), mask_len(0),
|
|
num_bits(0), first_set(0)
|
|
{
|
|
}
|
|
|
|
NormBitmask::~NormBitmask()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
bool NormBitmask::Init(UINT32 numBits)
|
|
{
|
|
if (mask) Destroy();
|
|
// Allocate memory for mask
|
|
unsigned int len = (numBits + 7) >> 3;
|
|
if ((mask = new unsigned char[len]))
|
|
{
|
|
num_bits = numBits;
|
|
mask_len = len;
|
|
Clear();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
} // end NormBitmask::Init()
|
|
|
|
void NormBitmask::Destroy()
|
|
{
|
|
if (mask)
|
|
{
|
|
delete[] mask;
|
|
mask = (unsigned char*)NULL;
|
|
num_bits = first_set = 0;
|
|
}
|
|
} // end NormBitmask::Destroy()
|
|
|
|
|
|
bool NormBitmask::GetNextSet(UINT32& index) const
|
|
{
|
|
//TRACE("NormBitmask::GetNextSet(%lu) first_set:%lu num_bits:%lu\n",
|
|
// index, first_set, num_bits);
|
|
if (index >= num_bits) return false;
|
|
if (index < first_set) return GetFirstSet(index);
|
|
UINT32 maskIndex = index >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]];
|
|
int remainder = index & 0x07;
|
|
for (int i = 0; i < w; i++)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc >= remainder)
|
|
{
|
|
index = (maskIndex << 3) + loc;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
while(++maskIndex < mask_len)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
index = (maskIndex << 3) + BITLOCS[mask[maskIndex]][0];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} // end NormBitmask::NextSet()
|
|
|
|
bool NormBitmask::GetPrevSet(UINT32& index) const
|
|
{
|
|
if (index >= num_bits) index = num_bits - 1;
|
|
if (index < first_set) return false;
|
|
UINT32 maskIndex = index >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
int remainder = index & 0x07;
|
|
for (int i = w; i >= 0; i--)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc <= remainder)
|
|
{
|
|
index = ((maskIndex << 3) + loc);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
maskIndex--;
|
|
UINT32 startIndex = first_set >> 3;
|
|
for (; maskIndex >= startIndex; maskIndex--)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
index = ((maskIndex << 3) + BITLOCS[mask[maskIndex]][w]);
|
|
return true;
|
|
}
|
|
}
|
|
return false; // (nothing prior was set)
|
|
} // end NormBitmask::PrevSet()
|
|
|
|
bool NormBitmask::GetNextUnset(UINT32& index) const
|
|
{
|
|
if (index >= num_bits) return false;
|
|
UINT32 next = index;
|
|
UINT32 maskIndex = next >> 3;
|
|
unsigned char bit = 0x80 >> (next & 0x07);
|
|
while (next < num_bits)
|
|
{
|
|
unsigned char val = mask[maskIndex];
|
|
if (val)
|
|
{
|
|
while (bit && (next < num_bits))
|
|
{
|
|
if (0 == (val & bit))
|
|
{
|
|
index = next;
|
|
return true;
|
|
}
|
|
next++;
|
|
bit >>= 0x01;
|
|
}
|
|
bit = 0x80;
|
|
maskIndex++;
|
|
}
|
|
else
|
|
{
|
|
index = next;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} // end NormBitmask::NextUnset()
|
|
|
|
|
|
bool NormBitmask::SetBits(UINT32 index, UINT32 count)
|
|
{
|
|
if (0 == count) return true;
|
|
if ((index+count) > num_bits) return false;
|
|
UINT32 maskIndex = index >> 3;
|
|
// To set appropriate bits in first byte
|
|
unsigned int bitIndex = index & 0x07;
|
|
unsigned int bitRemainder = 8 - bitIndex;
|
|
if (count <= bitRemainder)
|
|
{
|
|
mask[maskIndex] |= (0x00ff >> bitIndex) &
|
|
(0x00ff << (bitRemainder - count));
|
|
}
|
|
else
|
|
{
|
|
mask[maskIndex] |= 0x00ff >> bitIndex;
|
|
count -= bitRemainder;
|
|
UINT32 nbytes = count >> 3;
|
|
memset(&mask[++maskIndex], 0xff, nbytes);
|
|
count &= 0x07;
|
|
if (count)
|
|
mask[maskIndex+nbytes] |= 0xff << (8-count);
|
|
}
|
|
if (index < first_set) first_set = index;
|
|
return true;
|
|
} // end NormBitmask::SetBits()
|
|
|
|
|
|
bool NormBitmask::UnsetBits(UINT32 index, UINT32 count)
|
|
{
|
|
if ((index >= num_bits)|| (0 == count)) return true;
|
|
UINT32 end = index + count;
|
|
if (end > num_bits)
|
|
{
|
|
end = num_bits;
|
|
count = end - index;
|
|
}
|
|
UINT32 maskIndex = index >> 3;
|
|
// To unset appropriate bits in first byte
|
|
unsigned int bitIndex = index & 0x07;
|
|
unsigned int bitRemainder = 8 - bitIndex;
|
|
if (count <= bitRemainder)
|
|
{
|
|
mask[maskIndex] &= (0x00ff << bitRemainder) |
|
|
(0x00ff >> (bitIndex + count));
|
|
}
|
|
else
|
|
{
|
|
mask[maskIndex] &= 0x00ff << bitRemainder;
|
|
count -= bitRemainder;
|
|
UINT32 nbytes = count >> 3;
|
|
memset(&mask[++maskIndex], 0, nbytes);
|
|
count &= 0x07;
|
|
if (count) mask[maskIndex+nbytes] &= 0xff >> count;
|
|
}
|
|
if ((first_set >= index) && (end > first_set))
|
|
{
|
|
first_set = end;
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
return true;
|
|
} // end NormBitmask::UnsetBits()
|
|
|
|
// this = b
|
|
bool NormBitmask::Copy(const NormBitmask &b)
|
|
{
|
|
if (b.num_bits > num_bits) return false;
|
|
memcpy(mask, b.mask, b.mask_len);
|
|
(mask_len > b.mask_len) ?
|
|
memset(mask+b.mask_len, 0, mask_len - b.mask_len) : 0;
|
|
first_set = (b.first_set < b.num_bits) ? b.first_set : num_bits;
|
|
return true;
|
|
} // end NormBitmask::Copy()
|
|
|
|
// this = this | b
|
|
bool NormBitmask::Add(const NormBitmask& b)
|
|
{
|
|
if (b.num_bits > num_bits) return false;
|
|
for(unsigned int i = 0; i < b.mask_len; i++)
|
|
mask[i] |= b.mask[i];
|
|
if (b.first_set < first_set) first_set = b.first_set;
|
|
return true;
|
|
} // end NormBitmask::Add()
|
|
|
|
// this = this & ~b
|
|
bool NormBitmask::Subtract(const NormBitmask& b)
|
|
{
|
|
UINT32 len = (mask_len < b.mask_len) ? mask_len : b.mask_len;
|
|
for(UINT32 i = 0; i < len; i++)
|
|
mask[i] &= ~b.mask[i];
|
|
if (first_set >= b.first_set)
|
|
{
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
return true;
|
|
} // end NormBitmask::Subtract()
|
|
|
|
|
|
// this = ~this & b (this = b - this)
|
|
bool NormBitmask::XCopy(const NormBitmask& b)
|
|
{
|
|
if (b.num_bits > num_bits) return false;
|
|
unsigned int len = b.mask_len;
|
|
unsigned int begin = b.first_set >> 3;
|
|
if (begin) memset(mask, 0, begin);
|
|
for (unsigned int i = begin; i < len; i++)
|
|
mask[i] = b.mask[i] & ~mask[i];
|
|
if (len < mask_len) memset(&mask[len], 0, mask_len - len);
|
|
if (b.first_set < first_set)
|
|
{
|
|
first_set = b.first_set;
|
|
}
|
|
else
|
|
{
|
|
first_set = b.first_set;
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
return true;
|
|
} // end NormBitmask::XCopy()
|
|
|
|
// this = this & b
|
|
bool NormBitmask::Multiply(const NormBitmask& b)
|
|
{
|
|
UINT32 len = (mask_len < b.mask_len) ? mask_len : b.mask_len;
|
|
for(unsigned int i = 0; i < len; i++)
|
|
mask[i] |= b.mask[i];
|
|
if (len < mask_len) memset(&mask[len], 0, mask_len - len);
|
|
if (b.first_set > first_set)
|
|
{
|
|
first_set = b.first_set;
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
else if (first_set > b.first_set)
|
|
{
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
return true;
|
|
} // end NormBitmask::Multiply()
|
|
|
|
// this = this ^ b
|
|
bool NormBitmask::Xor(const NormBitmask& b)
|
|
{
|
|
if (b.num_bits > num_bits) return false;
|
|
for(unsigned int i = 0; i < b.mask_len; i++)
|
|
mask[i] ^= b.mask[i];
|
|
if (b.first_set == first_set)
|
|
{
|
|
if (!GetNextSet(first_set)) first_set = num_bits;
|
|
}
|
|
return true;
|
|
} // end NormBitmask::Xor()
|
|
|
|
void NormBitmask::Display(FILE* stream)
|
|
{
|
|
UINT32 index = 0;
|
|
for (UINT32 i = 0; i < num_bits; i++)
|
|
{
|
|
if (Test(index++)) fprintf(stream, "1"); else fprintf(stream, "0");
|
|
if (0x07 == (i & 0x07)) fprintf(stream, " ");
|
|
if (0x3f == (i & 0x3f)) fprintf(stream, "\n");
|
|
}
|
|
} // end NormBitmask::Display()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NormSlidingMask::NormSlidingMask()
|
|
: mask((unsigned char*)NULL), mask_len(0), num_bits(0),
|
|
start(0), end(0), offset(0)
|
|
{
|
|
}
|
|
|
|
|
|
NormSlidingMask::~NormSlidingMask()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
bool NormSlidingMask::Init(INT32 numBits, UINT32 rangeMask)
|
|
{
|
|
|
|
if (mask) Destroy();
|
|
if (numBits <= 0) return false;
|
|
UINT32 len = (numBits + 7) >> 3;
|
|
if ((mask = new unsigned char[len]))
|
|
{
|
|
range_mask = rangeMask;
|
|
range_sign = (rangeMask ^ (rangeMask >> 1));
|
|
mask_len = len;
|
|
num_bits = numBits;
|
|
Clear();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} // end NormSlidingMask::Init()
|
|
|
|
void NormSlidingMask::Destroy()
|
|
{
|
|
if (mask)
|
|
{
|
|
delete[] mask;
|
|
mask = NULL;
|
|
mask_len = num_bits = start = end = offset = 0;
|
|
}
|
|
} // end NormSlidingMask::Destroy()
|
|
|
|
bool NormSlidingMask::CanSet(UINT32 index) const
|
|
{
|
|
if (IsSet())
|
|
{
|
|
// Determine position with respect to current start
|
|
// and end, given the "offset" of the current start
|
|
INT32 pos = Delta(index, offset);
|
|
if (pos < 0)
|
|
{
|
|
// Precedes start.
|
|
pos += start;
|
|
if (pos < 0) pos += num_bits;
|
|
if (pos < 0)
|
|
{
|
|
// out of range
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// Is pos between end & start?
|
|
if (end < start)
|
|
{
|
|
if ((pos <= end) || (pos > start)) return false;
|
|
}
|
|
else
|
|
{
|
|
if ((pos <= end) && (pos > start)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
else if (pos < num_bits)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false; // out of range
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return true; // empty mask can be set in any fashion
|
|
}
|
|
} // end NormSlidingMask::CanSet()
|
|
|
|
bool NormSlidingMask::Set(UINT32 index)
|
|
{
|
|
ASSERT(CanSet(index));
|
|
if (IsSet())
|
|
{
|
|
// Determine position with respect to current start
|
|
// and end, given the "offset" of the current start
|
|
INT32 pos = Delta(index , offset);
|
|
if (pos < 0)
|
|
{
|
|
// Precedes start.
|
|
pos += start;
|
|
if (pos < 0) pos += num_bits;
|
|
if (pos < 0)
|
|
{
|
|
// out of range
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// Is pos between end & start?
|
|
if (end < start)
|
|
{
|
|
if ((pos <= end) || (pos > start)) return false;
|
|
}
|
|
else
|
|
{
|
|
if ((pos <= end) && (pos > start)) return false;
|
|
}
|
|
// Ok for new "start" && "offset"
|
|
start = pos;
|
|
offset = index;
|
|
}
|
|
}
|
|
else if (pos < num_bits)
|
|
{
|
|
pos += start;
|
|
if (pos >= num_bits) pos -= num_bits;
|
|
if (end < start)
|
|
{
|
|
if ((pos < start) && (pos > end)) end = pos;
|
|
}
|
|
else
|
|
{
|
|
if ((pos > end) || (pos < start)) end = pos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false; // out of range
|
|
}
|
|
ASSERT((pos >> 3) >= 0);
|
|
ASSERT((pos >> 3) < (INT32)mask_len);
|
|
mask[(pos >> 3)] |= (0x80 >> (pos & 0x07));
|
|
}
|
|
else
|
|
{
|
|
start = end = 0;
|
|
offset = index;
|
|
mask[0] = 0x80;
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Set()
|
|
|
|
bool NormSlidingMask::Unset(UINT32 index)
|
|
{
|
|
//ASSERT(CanSet(index));
|
|
if (IsSet())
|
|
{
|
|
INT32 pos = Delta(index, offset);
|
|
if (pos < 0)
|
|
{
|
|
return true; // out-of-range
|
|
}
|
|
else if (pos < num_bits)
|
|
{
|
|
// Is it in current range of set bits?
|
|
pos += start;
|
|
if (pos >= num_bits) pos -= num_bits;
|
|
if (end < start)
|
|
{
|
|
if ((pos > end) && (pos < start)) return true;
|
|
}
|
|
else
|
|
{
|
|
if ((pos < start) || (pos > end)) return true;
|
|
}
|
|
// Yes, it was in range.
|
|
// Unset the corresponding bit
|
|
ASSERT((pos >> 3) >= 0);
|
|
ASSERT((pos >> 3) < (INT32)mask_len);
|
|
mask[(pos >> 3)] &= ~(0x80 >> (pos & 0x07));
|
|
if (start == end)
|
|
{
|
|
ASSERT(pos == start);
|
|
start = end = num_bits;
|
|
return true;
|
|
}
|
|
if (start == pos)
|
|
{
|
|
UINT32 next = index;
|
|
if (!GetNextSet(next)) ASSERT(0);
|
|
INT32 delta = Delta(next, offset);
|
|
ASSERT(delta >= 0);
|
|
start += delta;
|
|
if (start >= num_bits) start -= num_bits;
|
|
offset = next;
|
|
}
|
|
if (pos == end)
|
|
{
|
|
UINT32 prev = index;
|
|
if (!GetPrevSet(prev)) ASSERT(0);
|
|
INT32 delta = Delta(prev, offset);
|
|
ASSERT(delta >= 0);
|
|
end = start + delta;
|
|
if (end >= num_bits) end -= num_bits;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return true; // out-of-range
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Unset()
|
|
|
|
bool NormSlidingMask::SetBits(UINT32 index, INT32 count)
|
|
{
|
|
ASSERT(CanSet(index));
|
|
ASSERT(CanSet(index+count-1));
|
|
if (count < 0) return false;
|
|
if (0 == count) return true;
|
|
INT32 firstPos, lastPos;
|
|
if (IsSet())
|
|
{
|
|
INT32 last = index + count - 1;
|
|
if (!CanSet(index)) return false;
|
|
if (!CanSet(last)) return false;
|
|
// Calculate first set bit position
|
|
firstPos = Delta(index, offset);
|
|
if (firstPos < 0)
|
|
{
|
|
// precedes start
|
|
firstPos += start;
|
|
if (firstPos < 0) firstPos += num_bits;
|
|
start = firstPos;
|
|
offset = index;
|
|
}
|
|
else
|
|
{
|
|
firstPos += start;
|
|
if (firstPos >= num_bits) firstPos -= num_bits;
|
|
}
|
|
// Calculate last set bit position
|
|
lastPos = Delta(last , offset);
|
|
if (lastPos > 0)
|
|
{
|
|
// Is post start, post end?
|
|
lastPos += start;
|
|
if (lastPos >= num_bits) lastPos -= num_bits;
|
|
if (end < start)
|
|
{
|
|
if ((lastPos < start) && (lastPos > end)) end = lastPos;
|
|
}
|
|
else
|
|
{
|
|
if ((lastPos > end) || (lastPos < start)) end = lastPos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lastPos += start;
|
|
if (lastPos < 0) lastPos += num_bits;
|
|
}
|
|
if (lastPos < firstPos)
|
|
{
|
|
// Set bits from firstPos to num_bits
|
|
count = num_bits - firstPos;
|
|
INT32 maskIndex = firstPos >> 3;
|
|
int bitIndex = firstPos & 0x07;
|
|
int bitRemainder = 8 - bitIndex;
|
|
ASSERT(maskIndex >= 0);
|
|
if (count <= bitRemainder)
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] |= (0x00ff >> bitIndex) &
|
|
(0x00ff << (bitRemainder - count));
|
|
}
|
|
else
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] |= 0x00ff >> bitIndex;
|
|
count -= bitRemainder;
|
|
INT32 nbytes = count >> 3;
|
|
ASSERT((maskIndex+1+nbytes) <= (INT32)mask_len);
|
|
memset(&mask[++maskIndex], 0xff, nbytes);
|
|
count &= 0x07;
|
|
if (count)
|
|
{
|
|
ASSERT((maskIndex+nbytes) >= 0);
|
|
ASSERT((maskIndex+nbytes) < (INT32)mask_len);
|
|
mask[maskIndex+nbytes] |= 0xff << (8-count);
|
|
}
|
|
}
|
|
firstPos = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (count > num_bits) return false;
|
|
start = firstPos = 0;
|
|
end = lastPos = (INT32)(count - 1);
|
|
offset = index;
|
|
}
|
|
// Set bits from firstPos to lastPos
|
|
count = lastPos - firstPos + 1;
|
|
INT32 maskIndex = firstPos >> 3;
|
|
int bitIndex = firstPos & 0x07;
|
|
int bitRemainder = 8 - bitIndex;
|
|
ASSERT(maskIndex >= 0);
|
|
if (count <= bitRemainder)
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] |= (0x00ff >> bitIndex) &
|
|
(0x00ff << (bitRemainder - count));
|
|
}
|
|
else
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] |= 0x00ff >> bitIndex;
|
|
count -= bitRemainder;
|
|
INT32 nbytes = count >> 3;
|
|
ASSERT((maskIndex+1+nbytes) <= (INT32)mask_len);
|
|
memset(&mask[++maskIndex], 0xff, nbytes);
|
|
count &= 0x07;
|
|
if (count)
|
|
{
|
|
ASSERT((maskIndex+nbytes) >= 0);
|
|
ASSERT((maskIndex+nbytes) < (INT32)mask_len);
|
|
mask[maskIndex+nbytes] |= 0xff << (8-count);
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::SetBits()
|
|
|
|
bool NormSlidingMask::UnsetBits(UINT32 index, INT32 count)
|
|
{
|
|
//ASSERT(CanSet(index));
|
|
//ASSERT(CanSet(index+count-1));
|
|
if (IsSet())
|
|
{
|
|
// Trim to fit as needed.
|
|
INT32 firstPos;
|
|
if (count <= 0) return true;
|
|
if (count > num_bits) count = num_bits;
|
|
INT32 delta = Delta(index , offset);
|
|
if (delta >= num_bits)
|
|
{
|
|
return true;
|
|
}
|
|
else if (delta <= 0)
|
|
{
|
|
firstPos = start;
|
|
count += delta;
|
|
if (count <= 0) return true;
|
|
}
|
|
else
|
|
{
|
|
firstPos = start + delta;
|
|
if (firstPos >= num_bits) firstPos -= num_bits;
|
|
}
|
|
UINT32 lastSet;
|
|
if (!GetLastSet(lastSet)) ASSERT(0);
|
|
delta = Delta((index+count-1), lastSet);
|
|
INT32 lastPos;
|
|
if (delta < 0)
|
|
{
|
|
lastPos = firstPos + count - 1;
|
|
if (lastPos >= num_bits) lastPos -= num_bits;
|
|
}
|
|
else
|
|
{
|
|
lastPos = end;
|
|
}
|
|
INT32 startPos;
|
|
if (lastPos < firstPos)
|
|
{
|
|
// Set bits from firstPos to num_bits
|
|
count = num_bits - firstPos;
|
|
INT32 maskIndex = firstPos >> 3;
|
|
int bitIndex = firstPos & 0x07;
|
|
int bitRemainder = 8 - bitIndex;
|
|
if (count <= bitRemainder)
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] &= (0x00ff << bitRemainder) |
|
|
(0x00ff >> (bitIndex + count));
|
|
}
|
|
else
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] &= 0x00ff << bitRemainder;
|
|
count -= bitRemainder;
|
|
UINT32 nbytes = count >> 3;
|
|
ASSERT((maskIndex+1+nbytes) <= mask_len);
|
|
memset(&mask[++maskIndex], 0, nbytes);
|
|
count &= 0x07;
|
|
if (count)
|
|
{
|
|
ASSERT((maskIndex+nbytes) < mask_len);
|
|
mask[maskIndex+nbytes] &= 0xff >> count;
|
|
}
|
|
}
|
|
startPos = 0;
|
|
}
|
|
else
|
|
{
|
|
startPos = firstPos;
|
|
}
|
|
// Unset bits from firstPos to lastPos
|
|
count = lastPos - startPos + 1;
|
|
INT32 maskIndex = startPos >> 3;
|
|
int bitIndex = startPos & 0x07;
|
|
int bitRemainder = 8 - bitIndex;
|
|
if (count <= bitRemainder)
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] &= (0x00ff << bitRemainder) |
|
|
(0x00ff >> (bitIndex + count));
|
|
}
|
|
else
|
|
{
|
|
ASSERT(maskIndex < (INT32)mask_len);
|
|
mask[maskIndex] &= 0x00ff << bitRemainder;
|
|
count -= bitRemainder;
|
|
UINT32 nbytes = count >> 3;
|
|
ASSERT((maskIndex+1+nbytes) <= mask_len);
|
|
memset(&mask[++maskIndex], 0, nbytes);
|
|
count &= 0x07;
|
|
if (count)
|
|
{
|
|
ASSERT((maskIndex+nbytes) < mask_len);
|
|
mask[maskIndex+nbytes] &= 0xff >> count;
|
|
}
|
|
}
|
|
// Calling these will properly update the offset/start/end state
|
|
if (start == firstPos)
|
|
{
|
|
if (end == lastPos)
|
|
{
|
|
start = end = num_bits;
|
|
}
|
|
else
|
|
{
|
|
Unset(offset);
|
|
}
|
|
}
|
|
else if (end == lastPos)
|
|
{
|
|
UINT32 lastSet;
|
|
GetLastSet(lastSet);
|
|
Unset(lastSet);
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::UnsetBits()
|
|
|
|
bool NormSlidingMask::Test(UINT32 index) const
|
|
{
|
|
if (IsSet())
|
|
{
|
|
INT32 pos = Delta(index , offset);
|
|
if (pos >= 0)
|
|
{
|
|
// Is it in range?
|
|
if (pos >= num_bits) return false;
|
|
pos += start;
|
|
if (pos >= num_bits) pos -= num_bits;
|
|
if (end < start)
|
|
{
|
|
if ((pos > end) && (pos < start)) return false;
|
|
}
|
|
else
|
|
{
|
|
if ((pos < start) || (pos > end)) return false;
|
|
}
|
|
// Test the corresponding bit
|
|
if (0 != (mask[(pos >> 3)] & (0x80 >> (pos & 0x07))))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} // end NormSlidingMask::Test()
|
|
|
|
|
|
bool NormSlidingMask::GetNextSet(UINT32& index) const
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 next = index;
|
|
INT32 pos = Delta(next, offset);
|
|
if (pos >= 0)
|
|
{
|
|
// Is it in range?
|
|
if (pos >= num_bits) return false;
|
|
pos += start;
|
|
if (pos >= num_bits) pos -= num_bits;
|
|
|
|
if (end < start)
|
|
{
|
|
if ((pos > end) && (pos < start)) return false;
|
|
}
|
|
else
|
|
{
|
|
if ((pos < start) || (pos > end)) return false;
|
|
}
|
|
// Seek next set bit
|
|
UINT32 maskIndex = pos >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]];
|
|
int remainder = pos & 0x07;
|
|
for (int i = 0; i < w; i++)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc >= remainder)
|
|
{
|
|
pos = (maskIndex << 3) + loc;
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
maskIndex++;
|
|
if (end < pos)
|
|
{
|
|
for (; maskIndex < mask_len; maskIndex++)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
pos = (maskIndex << 3) + BITLOCS[mask[maskIndex]][0];
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
maskIndex = 0;
|
|
}
|
|
UINT32 endIndex = end >> 3;
|
|
for (; maskIndex <= endIndex; maskIndex++)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
pos = (maskIndex << 3) + BITLOCS[mask[maskIndex]][0];
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return false; // indicates nothing was set
|
|
} // end NormSlidingMask::GetNextSet()
|
|
|
|
bool NormSlidingMask::GetPrevSet(UINT32& index) const
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 prev = index;
|
|
INT32 pos = Delta(prev, offset);
|
|
if (pos >= 0)
|
|
{
|
|
// Is it in range?
|
|
if (pos >= num_bits)
|
|
{
|
|
return false;
|
|
}
|
|
pos += start;
|
|
if (pos >= num_bits) pos -= num_bits;
|
|
if (end < start)
|
|
{
|
|
if ((pos > end) && (pos < start)) return false;
|
|
}
|
|
else
|
|
{
|
|
if ((pos < start) || (pos > end)) return false;
|
|
}
|
|
// Seek prev set bits, starting with index
|
|
INT32 maskIndex = pos >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
int remainder = pos & 0x07;
|
|
for (int i = w; i >= 0; i--)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc <= remainder)
|
|
{
|
|
pos = (maskIndex << 3) + loc;
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
maskIndex--;
|
|
if (pos < start)
|
|
{
|
|
for(; maskIndex >= 0; maskIndex--)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
pos = (maskIndex << 3) + BITLOCS[mask[maskIndex]][w];
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
maskIndex = mask_len - 1;
|
|
}
|
|
INT32 startIndex = start >> 3;
|
|
for (; maskIndex >= startIndex; maskIndex--)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
pos = (maskIndex << 3) + BITLOCS[mask[maskIndex]][w];
|
|
pos -= start;
|
|
if (pos < 0) pos += num_bits;
|
|
index = offset + pos;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false; // indicates nothing prior was set
|
|
} // end NormSlidingMask::GetPrevSet()
|
|
|
|
/*UINT32 NormSlidingMask::RawNextSet(const char* mask, INT32 index, INT32 end)
|
|
{
|
|
// Seek next set bit
|
|
UINT32 maskIndex = index >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]];
|
|
int remainder = index & 0x07;
|
|
for (int i = 0; i < w; i++)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc >= remainder)
|
|
return ((maskIndex << 3) + loc);
|
|
}
|
|
}
|
|
maskIndex++;
|
|
UINT32 endIndex = end >> 3;
|
|
for (; maskIndex <= endIndex; maskIndex++)
|
|
{
|
|
if (mask[maskIndex])
|
|
return((maskIndex << 3) + BITLOCS[mask[maskIndex]][0]);
|
|
}
|
|
return (index-1); // (nothing was set)
|
|
} // end NormSlidingMask::RawNextSet()
|
|
|
|
UINT32 NormSlidingMask::RawPrevSet(const char* mask, INT32 index, INT32 start)
|
|
{
|
|
// Seek prev set bits, starting with index
|
|
UINT32 maskIndex = index >> 3;
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
int remainder = index & 0x07;
|
|
for (int i = w; i >= 0; i--)
|
|
{
|
|
int loc = BITLOCS[mask[maskIndex]][i];
|
|
if (loc <= remainder)
|
|
{
|
|
return((maskIndex << 3) + loc);
|
|
}
|
|
}
|
|
}
|
|
maskIndex--;
|
|
UINT32 startIndex = start >> 3;
|
|
for (; maskIndex >= startIndex; maskIndex--)
|
|
{
|
|
if (mask[maskIndex])
|
|
{
|
|
int w = WEIGHT[mask[maskIndex]] - 1;
|
|
return((maskIndex << 3) + BITLOCS[mask[maskIndex]][w]);
|
|
}
|
|
}
|
|
return (index+1); // (nothing was set)
|
|
} // end NormSlidingMask::RawPrevSet()*/
|
|
|
|
bool NormSlidingMask::Copy(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
INT32 range = b.end - b.start;
|
|
if (range < 0) range += b.num_bits;
|
|
if (range <= num_bits)
|
|
{
|
|
start = b.start & 0x07;
|
|
UINT32 bLastSet;
|
|
b.GetLastSet(bLastSet);
|
|
UINT32 bFirstSet;
|
|
b.GetFirstSet(bFirstSet);
|
|
end = bLastSet - bFirstSet + start;
|
|
offset = b.offset;
|
|
// Copy start to mask_len
|
|
INT32 startIndex = b.start >> 3;
|
|
INT32 endIndex = b.end >> 3;
|
|
if (b.end < b.start)
|
|
{
|
|
ASSERT((b.mask_len - startIndex) <= mask_len);
|
|
memcpy(mask, b.mask+startIndex, b.mask_len - startIndex);
|
|
ASSERT((b.mask_len - startIndex + endIndex) <= mask_len);
|
|
//memcpy(mask+b.mask_len-startIndex, b.mask, endIndex+1); // old
|
|
memcpy(mask+b.mask_len-startIndex, b.mask, endIndex); // new
|
|
// Clear any possible start/end overlap
|
|
if (mask_len > b.mask_len)
|
|
{
|
|
unsigned int remainder = start & 0x07;
|
|
if (remainder) mask[0] &= 0xff >> remainder;
|
|
remainder = end & 0x7;
|
|
if (remainder)
|
|
{
|
|
ASSERT((startIndex+endIndex) < (INT32)mask_len);
|
|
mask[startIndex+endIndex] &= 0xff << (8 - remainder);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT((endIndex-startIndex+1) <= (INT32)mask_len);
|
|
memcpy(mask, b.mask+startIndex, endIndex-startIndex+1);
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Clear();
|
|
return true;
|
|
}
|
|
} // end NormSlidingMask::Copy()
|
|
|
|
// Logically OR two bit mask such that "this = (this | b)"
|
|
bool NormSlidingMask::Add(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 bFirstSet;
|
|
b.GetFirstSet(bFirstSet);
|
|
if (!CanSet(bFirstSet)) return false;
|
|
UINT32 bLastSet;
|
|
b.GetFirstSet(bLastSet);
|
|
if (!CanSet(bLastSet)) return false;
|
|
INT32 range = b.end - b.start;
|
|
if (range < 0) range += b.num_bits;
|
|
UINT32 index;
|
|
b.GetFirstSet(index);
|
|
for (INT32 i = 0; i < range; i++)
|
|
{
|
|
// (TBD) Improve performance by getting/setting
|
|
// ranges of set bits.
|
|
if (b.Test(index)) Set(index);
|
|
index++;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return Copy(b);
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Add()
|
|
|
|
// A sort of logical subtraction "this = (this & ~b)"
|
|
// This leaves us with bits uniquely set in "this"
|
|
bool NormSlidingMask::Subtract(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 index = offset;
|
|
INT32 range = end - start;
|
|
if (range < 0) range += num_bits;
|
|
for (INT32 i = 0; i < range; i++)
|
|
{
|
|
if (Test(index) && b.Test(index)) Unset(index);
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Subtract()
|
|
|
|
// A sort of logical subtraction "this = (~this & b)"
|
|
// This leaves us with bits uniquely set in "b"
|
|
bool NormSlidingMask::XCopy(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 bFirstSet;
|
|
b.GetFirstSet(bFirstSet);
|
|
if (!CanSet(bFirstSet)) return false;
|
|
UINT32 bLastSet;
|
|
b.GetFirstSet(bLastSet);
|
|
if (!CanSet(bLastSet)) return false;
|
|
UINT32 index;
|
|
b.GetFirstSet(index);
|
|
INT32 range = b.end - b.start;
|
|
if (range < 0) range += b.num_bits;
|
|
for (INT32 i = 0; i < range; i++)
|
|
{
|
|
if (Test(index))
|
|
Unset(index);
|
|
else if (b.Test(index))
|
|
Set(index);
|
|
index++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return Copy(b);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Clear();
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::XCopy()
|
|
|
|
// Logically AND two bit mask such that "this = (this & b)"
|
|
bool NormSlidingMask::Multiply(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
if (IsSet())
|
|
{
|
|
UINT32 index = offset;
|
|
INT32 range = end - start;
|
|
if (range < 0) range += num_bits;
|
|
for (INT32 i = 0; i < range; i++)
|
|
{
|
|
if (Test(index) && !b.Test(index)) Unset(index);
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Clear();
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Multiply()
|
|
|
|
// Logically XOR two bit mask such that "this = (this ^ b)"
|
|
// (TBD) rewrite for byte-based operation for better efficiency
|
|
bool NormSlidingMask::Xor(const NormSlidingMask& b)
|
|
{
|
|
if (b.IsSet())
|
|
{
|
|
UINT32 bFirstSet;
|
|
b.GetFirstSet(bFirstSet);
|
|
if (!CanSet(bFirstSet)) return false;
|
|
UINT32 bLastSet;
|
|
b.GetFirstSet(bLastSet);
|
|
if (!CanSet(bLastSet)) return false;
|
|
UINT32 index;
|
|
b.GetFirstSet(index);
|
|
INT32 range = b.end - b.start;
|
|
if (range < 0) range += b.num_bits;
|
|
for (INT32 i = 0; i < range; i++)
|
|
{
|
|
if (b.Test(index)) Invert(index);
|
|
index++;
|
|
}
|
|
}
|
|
return true;
|
|
} // end NormSlidingMask::Xor()
|
|
|
|
void NormSlidingMask::Display(FILE* stream)
|
|
{
|
|
UINT32 index = offset;
|
|
for (INT32 i = 0; i < num_bits; i++)
|
|
{
|
|
if (Test(index++)) fprintf(stream, "1"); else fprintf(stream, "0");
|
|
if (0x07 == (i & 0x07)) fprintf(stream, " ");
|
|
if (0x3f == (i & 0x3f)) fprintf(stream, "\n");
|
|
}
|
|
} // end NormSlidingMask::Display()
|
|
|
|
void NormSlidingMask::Debug(INT32 theCount)
|
|
{
|
|
UINT32 index = offset;
|
|
theCount = MIN(theCount, num_bits);
|
|
DMSG(0, "NormSlidingMask::Debug() offset:%lu\n ", index);
|
|
INT32 i;
|
|
for (i = 0; i < theCount; i++)
|
|
{
|
|
if (Test(index++)) DMSG(0, "1"); else DMSG(0, "0");
|
|
if (0x07 == (i & 0x07)) DMSG(0, " ");
|
|
if (0x3f == (i & 0x3f)) DMSG(0, "\n ");
|
|
}
|
|
if (0x3f != (i & 0x3f)) DMSG(0, "\n");
|
|
} // end NormSlidingMask::Debug()
|