int SelectBackend(int I, int[] AbsRank, short[] RelRank, uint[] bitmap)
{
if (I < 1) {
return -1;
}
// 00R00R00R00A00R00R00R00A00R00R00R00A
// 0 1 2 3 4 5 6 7 8
// 0 1 2
// 012345678901234567890123456789012345
// X X X X
// TODO: check selects for out of bounds
int abs_pos = GenericSearch.FindFirst<int> (I, AbsRank, 0, AbsRank.Length);
int pos = 0;
int min = 0;
if (abs_pos >= 0 && I == AbsRank[abs_pos]) {
abs_pos--;
}
// Console.WriteLine ("ABS I: {0}, AbsRank.Count: {1}, abs_pos: {2}",
// I, AbsRank.Count, abs_pos);
if (abs_pos >= 0) {
pos = (abs_pos + 1) * this.SuperBlockSize;
I -= AbsRank[abs_pos];
min = pos - abs_pos - 1;
}
int diff = 0;
{
int max = Math.Min (min + this.SuperBlockSize - 1, RelRank.Length);
int rel_pos = GenericSearch.FindFirst<short> ((short)I, RelRank, min, max);
if (rel_pos >= 0 && I == RelRank[rel_pos]) {
rel_pos--;
}
// Console.WriteLine ("REL I: {0}, RelRank.Count: {1}, min: {2}, max: {3}, rel_pos: {4}",
// I, RelRank.Count, min, max, rel_pos);
if (rel_pos >= min) {
diff = rel_pos + 1 - min;
I -= RelRank[rel_pos];
}
}
pos += diff;
pos *= this.BlockSize;
if (I > 0) {
if (pos == 0) {
return BitAccess.Select1 (bitmap, 0, this.BlockSize, I);
} else {
return (pos << 5) + BitAccess.Select1 (bitmap, pos, this.BlockSize, I);
}
} else {
return pos << 5;
}
}