Make slightly more sense of CompactArrayUtil

... and make it less vanilla copy pasty

The magic array is a reciprocal table of 3-tuples, although 1 and 2 are always the same but for the ones including right shifts
This commit is contained in:
Nassim Jahnke 2022-12-02 14:34:32 +01:00
parent e0cd121a58
commit 9be32ca18b
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
1 changed files with 30 additions and 31 deletions

View File

@ -24,29 +24,28 @@ package com.viaversion.viaversion.util;
import java.util.function.IntToLongFunction;
public class CompactArrayUtil {
//Oh no
private static final int[] MAGIC = {
-1, -1, 0, Integer.MIN_VALUE, 0, 0, 1431655765, 1431655765, 0, Integer.MIN_VALUE,
0, 1, 858993459, 858993459, 0, 715827882, 715827882, 0, 613566756, 613566756,
0, Integer.MIN_VALUE, 0, 2, 477218588, 477218588, 0, 429496729, 429496729, 0,
390451572, 390451572, 0, 357913941, 357913941, 0, 330382099, 330382099, 0, 306783378,
306783378, 0, 286331153, 286331153, 0, Integer.MIN_VALUE, 0, 3, 252645135, 252645135,
0, 238609294, 238609294, 0, 226050910, 226050910, 0, 214748364, 214748364, 0,
204522252, 204522252, 0, 195225786, 195225786, 0, 186737708, 186737708, 0, 178956970,
178956970, 0, 171798691, 171798691, 0, 165191049, 165191049, 0, 159072862, 159072862,
0, 153391689, 153391689, 0, 148102320, 148102320, 0, 143165576, 143165576, 0,
138547332, 138547332, 0, Integer.MIN_VALUE, 0, 4, 130150524, 130150524, 0, 126322567,
126322567, 0, 122713351, 122713351, 0, 119304647, 119304647, 0, 116080197, 116080197,
0, 113025455, 113025455, 0, 110127366, 110127366, 0, 107374182, 107374182, 0,
104755299, 104755299, 0, 102261126, 102261126, 0, 99882960, 99882960, 0, 97612893,
97612893, 0, 95443717, 95443717, 0, 93368854, 93368854, 0, 91382282, 91382282,
0, 89478485, 89478485, 0, 87652393, 87652393, 0, 85899345, 85899345, 0,
84215045, 84215045, 0, 82595524, 82595524, 0, 81037118, 81037118, 0, 79536431,
79536431, 0, 78090314, 78090314, 0, 76695844, 76695844, 0, 75350303, 75350303,
0, 74051160, 74051160, 0, 72796055, 72796055, 0, 71582788, 71582788, 0,
70409299, 70409299, 0, 69273666, 69273666, 0, 68174084, 68174084, 0, Integer.MIN_VALUE,
0, 5};
public final class CompactArrayUtil {
private static final long[] RECIPROCAL_MULT_AND_ADD = {
0xffffffffL, 0x00000000, 0x55555555, 0x00000000, 0x33333333, 0x2aaaaaaa, 0x24924924, 0x00000000,
0x1c71c71c, 0x19999999, 0x1745d174, 0x15555555, 0x13b13b13, 0x12492492, 0x11111111, 0x00000000,
0xf0f0f0f, 0xe38e38e, 0xd79435e, 0xccccccc, 0xc30c30c, 0xba2e8ba, 0xb21642c, 0xaaaaaaa,
0xa3d70a3, 0x9d89d89, 0x97b425e, 0x9249249, 0x8d3dcb0, 0x8888888, 0x8421084, 0x00000000,
0x7c1f07c, 0x7878787, 0x7507507, 0x71c71c7, 0x6eb3e45, 0x6bca1af, 0x6906906, 0x6666666,
0x63e7063, 0x6186186, 0x5f417d0, 0x5d1745d, 0x5b05b05, 0x590b216, 0x572620a, 0x5555555,
0x5397829, 0x51eb851, 0x5050505, 0x4ec4ec4, 0x4d4873e, 0x4bda12f, 0x4a7904a, 0x4924924,
0x47dc11f, 0x469ee58, 0x456c797, 0x4444444, 0x4325c53, 0x4210842, 0x4104104, 0x00000000
};
// Incrementally shift with each 0x80000000/0x00000000 tuple
private static final int[] RECIPROCAL_RIGHT_SHIFT = {
0, 0, 0, 1, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 3,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 4,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 5
};
private CompactArrayUtil() {
throw new AssertionError();
@ -55,10 +54,10 @@ public class CompactArrayUtil {
public static long[] createCompactArrayWithPadding(int bitsPerEntry, int entries, IntToLongFunction valueGetter) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
char valuesPerLong = (char) (64 / bitsPerEntry);
int magicIndex = 3 * (valuesPerLong - 1);
long divideMul = Integer.toUnsignedLong(MAGIC[magicIndex]);
long divideAdd = Integer.toUnsignedLong(MAGIC[magicIndex + 1]);
int divideShift = MAGIC[magicIndex + 2];
int magicIndex = valuesPerLong - 1;
long divideAdd = RECIPROCAL_MULT_AND_ADD[magicIndex];
long divideMul = divideAdd != 0 ? divideAdd : 0x80000000L; // Special case for the 0x80000000/0x00000000 tuple
int divideShift = RECIPROCAL_RIGHT_SHIFT[magicIndex];
int size = (entries + valuesPerLong - 1) / valuesPerLong;
long[] data = new long[size];
@ -76,10 +75,10 @@ public class CompactArrayUtil {
public static void iterateCompactArrayWithPadding(int bitsPerEntry, int entries, long[] data, BiIntConsumer consumer) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
char valuesPerLong = (char) (64 / bitsPerEntry);
int magicIndex = 3 * (valuesPerLong - 1);
long divideMul = Integer.toUnsignedLong(MAGIC[magicIndex]);
long divideAdd = Integer.toUnsignedLong(MAGIC[magicIndex + 1]);
int divideShift = MAGIC[magicIndex + 2];
int magicIndex = valuesPerLong - 1;
long divideAdd = RECIPROCAL_MULT_AND_ADD[magicIndex];
long divideMul = divideAdd != 0 ? divideAdd : 0x80000000L;
int divideShift = RECIPROCAL_RIGHT_SHIFT[magicIndex];
for (int i = 0; i < entries; i++) {
int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);