in graphjet-core/src/main/java/com/twitter/graphjet/math/AliasTableUtil.java [46:114]
public static void constructAliasTable(int[] aliasTableArray) {
int aliasTableSize = getAliasTableSize(aliasTableArray);
int averageWeight = getAliasTableAverageWeight(aliasTableArray);
// TODO(aneesh): both these arrays can be captured in a single array
int[] belowAverageIndices = new int[aliasTableSize];
int numBelowAverage = 0;
int[] aboveAverageIndices = new int[aliasTableSize];
int numAboveAverage = 0;
// First pass through the list
for (int i = 0; i < aliasTableSize; i++) {
int weight = getWeight(aliasTableArray, i);
if (weight == averageWeight) {
setNextEntry(aliasTableArray, i, -1);
} else if (weight < averageWeight) {
if (numAboveAverage > 0) {
int donatingItemIndex = aboveAverageIndices[--numAboveAverage];
setNextEntry(aliasTableArray, i, getEntry(aliasTableArray, donatingItemIndex));
int newWeight =
getWeight(aliasTableArray, donatingItemIndex) - (averageWeight - weight);
setWeight(aliasTableArray, donatingItemIndex, newWeight);
if (newWeight == averageWeight) {
setNextEntry(aliasTableArray, donatingItemIndex, -1);
} else if (newWeight < averageWeight) {
belowAverageIndices[numBelowAverage++] = donatingItemIndex;
} else {
aboveAverageIndices[numAboveAverage++] = donatingItemIndex;
}
} else {
belowAverageIndices[numBelowAverage++] = i;
}
} else {
aboveAverageIndices[numAboveAverage++] = i;
}
}
// This is for balancing the below average elements, but due to limited precision there might
// be some remaining elements
// TODO (aneesh): convert to for loop
while (numBelowAverage > 0 && numAboveAverage > 0) {
int entryIndex = belowAverageIndices[--numBelowAverage];
int weight = getWeight(aliasTableArray, entryIndex);
int donatingElementIndex = aboveAverageIndices[--numAboveAverage];
setNextEntry(aliasTableArray, entryIndex, getEntry(aliasTableArray, donatingElementIndex));
int newWeight =
getWeight(aliasTableArray, donatingElementIndex) - (averageWeight - weight);
setWeight(aliasTableArray, donatingElementIndex, newWeight);
if (newWeight == averageWeight) {
setNextEntry(aliasTableArray, donatingElementIndex, -1);
} else if (newWeight < averageWeight) {
belowAverageIndices[numBelowAverage++] = donatingElementIndex;
} else {
aboveAverageIndices[numAboveAverage++] = donatingElementIndex;
}
}
// Due to limited precision, it is possible we get here, so we do the final cleanup
for (int i = numBelowAverage - 1; i >= 0; i--) {
int index = belowAverageIndices[i];
setWeight(aliasTableArray, index, averageWeight);
setNextEntry(aliasTableArray, index, -1);
}
for (int i = numAboveAverage - 1; i >= 0; i--) {
int index = aboveAverageIndices[i];
setWeight(aliasTableArray, index, averageWeight);
setNextEntry(aliasTableArray, index, -1);
}
}