370 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| 		}
 | |
| 	}
 | |
| }
 |