diff --git a/api/src/main/java/com/viaversion/viaversion/util/CompactArrayUtil.java b/api/src/main/java/com/viaversion/viaversion/util/CompactArrayUtil.java index d8eb02582..5c8800375 100644 --- a/api/src/main/java/com/viaversion/viaversion/util/CompactArrayUtil.java +++ b/api/src/main/java/com/viaversion/viaversion/util/CompactArrayUtil.java @@ -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);