minecraft-src/net/minecraft/util/SimpleBitStorage.java
2025-07-04 01:41:11 +03:00

370 lines
6 KiB
Java

package net.minecraft.util;
import java.util.function.IntConsumer;
import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.Nullable;
public class SimpleBitStorage implements BitStorage {
private static final int[] MAGIC = new int[]{
-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
};
private final long[] data;
private final int bits;
private final long mask;
private final int size;
private final int valuesPerLong;
private final int divideMul;
private final int divideAdd;
private final int divideShift;
public SimpleBitStorage(int bits, int size, int[] data) {
this(bits, size);
int i = 0;
int j;
for (j = 0; j <= size - this.valuesPerLong; j += this.valuesPerLong) {
long l = 0L;
for (int k = this.valuesPerLong - 1; k >= 0; k--) {
l <<= bits;
l |= data[j + k] & this.mask;
}
this.data[i++] = l;
}
int m = size - j;
if (m > 0) {
long n = 0L;
for (int o = m - 1; o >= 0; o--) {
n <<= bits;
n |= data[j + o] & this.mask;
}
this.data[i] = n;
}
}
public SimpleBitStorage(int bits, int size) {
this(bits, size, (long[])null);
}
public SimpleBitStorage(int bits, int size, @Nullable long[] data) {
Validate.inclusiveBetween(1L, 32L, (long)bits);
this.size = size;
this.bits = bits;
this.mask = (1L << bits) - 1L;
this.valuesPerLong = (char)(64 / bits);
int i = 3 * (this.valuesPerLong - 1);
this.divideMul = MAGIC[i + 0];
this.divideAdd = MAGIC[i + 1];
this.divideShift = MAGIC[i + 2];
int j = (size + this.valuesPerLong - 1) / this.valuesPerLong;
if (data != null) {
if (data.length != j) {
throw new SimpleBitStorage.InitializationException("Invalid length given for storage, got: " + data.length + " but expected: " + j);
}
this.data = data;
} else {
this.data = new long[j];
}
}
private int cellIndex(int index) {
long l = Integer.toUnsignedLong(this.divideMul);
long m = Integer.toUnsignedLong(this.divideAdd);
return (int)(index * l + m >> 32 >> this.divideShift);
}
@Override
public int getAndSet(int index, int value) {
Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
Validate.inclusiveBetween(0L, this.mask, (long)value);
int i = this.cellIndex(index);
long l = this.data[i];
int j = (index - i * this.valuesPerLong) * this.bits;
int k = (int)(l >> j & this.mask);
this.data[i] = l & ~(this.mask << j) | (value & this.mask) << j;
return k;
}
@Override
public void set(int index, int value) {
Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
Validate.inclusiveBetween(0L, this.mask, (long)value);
int i = this.cellIndex(index);
long l = this.data[i];
int j = (index - i * this.valuesPerLong) * this.bits;
this.data[i] = l & ~(this.mask << j) | (value & this.mask) << j;
}
@Override
public int get(int index) {
Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index);
int i = this.cellIndex(index);
long l = this.data[i];
int j = (index - i * this.valuesPerLong) * this.bits;
return (int)(l >> j & this.mask);
}
@Override
public long[] getRaw() {
return this.data;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getBits() {
return this.bits;
}
@Override
public void getAll(IntConsumer consumer) {
int i = 0;
for (long l : this.data) {
for (int j = 0; j < this.valuesPerLong; j++) {
consumer.accept((int)(l & this.mask));
l >>= this.bits;
if (++i >= this.size) {
return;
}
}
}
}
@Override
public void unpack(int[] array) {
int i = this.data.length;
int j = 0;
for (int k = 0; k < i - 1; k++) {
long l = this.data[k];
for (int m = 0; m < this.valuesPerLong; m++) {
array[j + m] = (int)(l & this.mask);
l >>= this.bits;
}
j += this.valuesPerLong;
}
int k = this.size - j;
if (k > 0) {
long l = this.data[i - 1];
for (int m = 0; m < k; m++) {
array[j + m] = (int)(l & this.mask);
l >>= this.bits;
}
}
}
@Override
public BitStorage copy() {
return new SimpleBitStorage(this.bits, this.size, (long[])this.data.clone());
}
public static class InitializationException extends RuntimeException {
InitializationException(String message) {
super(message);
}
}
}