Browse Source

Added a bunch of new code, without testing; among these is a middle-square PRNG to replace the LFSR one, since it's much faster in software

master
Thomas Johnson 2 years ago
parent
commit
3f00bfcb71
  1. 2
      gradle.properties
  2. 12
      src/main/java/t/j/dual/FiniteSampledGrid.java
  3. 6
      src/main/java/t/j/dual/GridCache.java
  4. 96
      src/main/java/t/j/dual/IntGrid.java
  5. 68
      src/main/java/t/j/dual/PointGrid.java
  6. 16
      src/main/java/t/j/dual/PointList.java
  7. 6
      src/main/java/t/j/dual/PointWorld.java
  8. 13
      src/main/java/t/j/dual/SampledGrid.java
  9. 33
      src/main/java/t/j/dual/SlicedFiniteSampledGrid.java
  10. 45
      src/main/java/t/j/dual/StoredFiniteSampledGrid.java
  11. 65
      src/main/java/t/j/dual/Utilities.java

2
gradle.properties

@ -1,4 +1,4 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
org.gradle.daemon=true

12
src/main/java/t/j/dual/FiniteSampledGrid.java

@ -0,0 +1,12 @@
package t.j.dual;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
import t.j.dual.SlicedFiniteSampledGrid;
public interface FiniteSampledGrid<T> extends SampledGrid<T> {
public IntGrid getGrid();
public T get(Vec3i cell);
}

6
src/main/java/t/j/dual/GridCache.java

@ -8,9 +8,9 @@ import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public class GridCache<T> {
Function<Vec3i, T> source;
WeakHashMap<Vec3i, SoftReference<CacheEntry<T>>> cacheMap;
public class GridCache<T> implements SampledGrid<T> {
private Function<Vec3i, T> source;
private WeakHashMap<Vec3i, SoftReference<CacheEntry<T>>> cacheMap;
class CacheEntry<T> {
public Vec3i keyRef;

96
src/main/java/t/j/dual/IntGrid.java

@ -0,0 +1,96 @@
package t.j.dual;
import java.util.Iterator;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public class IntGrid implements Iterable<Vec3i> {
public Vec3i origin;
public Vec3i extent;
public class Iter implements Iterator<Vec3i> {
public IntGrid grid;
int x, y, z;
public Iter(IntGrid grid) {
this.x = 0;
this.y = 0;
this.z = 0;
this.grid = grid;
}
public boolean hasNext() {
return z < grid.extent.getZ();
}
public Vec3i next() {
Vec3i result = new Vec3i(x + grid.origin.getX(), y + grid.origin.getY(), z + grid.origin.getZ());
x += 1;
if (x == grid.extent.getX()) {
x = 0;
y += 1;
if (y == grid.extent.getY()) {
y = 0;
z += 1;
}
}
return result;
}
}
public IntGrid(Vec3i origin, Vec3i extent) {
this.origin = origin;
this.extent = extent;
}
public int numPoints() {
return extent.getX() * extent.getY() * extent.getZ();
}
public Vec3i translateToFrame(Vec3i in) {
return Utilities.viSub(in, origin);
}
public Vec3i translateFromFrame(Vec3i in) {
return Utilities.viAdd(in, origin);
}
public Vec3i nToGridCoordsInFrame(int idx) {
int x = idx / (extent.getY() * extent.getZ());
int remX = idx % (extent.getY() * extent.getZ());
int y = remX / extent.getZ();
int z = remX % extent.getZ();
return new Vec3i(x, y, z);
}
public Vec3i nToGridCoords(int idx) {
return translateFromFrame(nToGridCoordsInFrame(idx));
}
public int gridCoordsToN(Vec3i ucoords) {
Vec3i coords = translateToFrame(ucoords);
return (coords.getX() * extent.getY() + coords.getY()) * extent.getZ() + coords.getZ();
}
public Iterator<Vec3i> iterator() {
return new Iter(this);
}
public Vec3i origin() {
return origin;
}
// Not actually in the grid, since the grid is bounded strictly less than this
public Vec3i remote() {
return new Vec3i(origin.getX() + extent.getX(), origin.getY() + extent.getY(), origin.getZ() + extent.getZ());
}
public IntGrid intersect(IntGrid other) {
Vec3i newOrigin = Utilities.ewiMax(origin, other.origin);
Vec3i newRemote = Utilities.ewiMin(remote(), other.remote());
Vec3i newExtent = Utilities.viSub(newRemote, newOrigin);
return new IntGrid(newOrigin, newExtent);
}
}

68
src/main/java/t/j/dual/PointGrid.java

@ -4,67 +4,58 @@ import java.util.Iterator;
import net.minecraft.util.math.*;
import t.j.dual.PointList;
public class PointGrid implements PointList {
public class PointGrid implements Iterable<Vec3d> {
public IntGrid domain;
public Vec3d origin;
public Vec3d step;
public Vec3i extent;
public class Iter implements Iterator<Vec3d> {
public Iterator<Vec3i> subIter;
public PointGrid grid;
int x, y, z;
public Iter(PointGrid grid) {
this.x = 0;
this.y = 0;
this.z = 0;
this.grid = grid;
this.subIter = grid.domain.iterator();
}
public boolean hasNext() {
return z < grid.extent.getZ();
return subIter.hasNext();
}
public Vec3d next() {
Vec3d result = new Vec3d(origin.x + x * step.x, origin.y + y * step.y, origin.z + z * step.z);
x += 1;
if (x == grid.extent.getX()) {
x = 0;
y += 1;
if (y == grid.extent.getY()) {
y = 0;
z += 1;
}
}
return result;
return grid.getCoords(subIter.next());
}
}
public PointGrid(Vec3d origin, Vec3i extent, Vec3d step) {
public PointGrid(Vec3d origin, IntGrid intGrid, Vec3d step) {
this.domain = intGrid;
this.origin = origin;
this.extent = extent;
this.step = step;
}
public PointGrid(Vec3d origin, Vec3d remote, Vec3i extent) {
public PointGrid(Vec3d origin, Vec3d remote, IntGrid intGrid) {
this.domain = intGrid;
this.origin = origin;
this.extent = extent;
Vec3d size = remote.subtract(origin);
Vec3d divisor = new Vec3d(extent.getX() - 1, extent.getY() - 1, extent.getZ() - 1);
Vec3d divisor = new Vec3d(domain.extent.getX() - 1, domain.extent.getY() - 1, domain.extent.getZ() - 1);
this.step = new Vec3d(size.x / divisor.x, size.y / divisor.y, size.z / divisor.z);
}
public int numPoints() {
return extent.getX() * extent.getY() * extent.getZ();
return domain.numPoints();
}
public Vec3d getCoords(Vec3i untranslated) {
return getCoordsInFrame(domain.translateToFrame(untranslated));
}
public Vec3d getCoordsInFrame(Vec3i at) {
return new Vec3d(origin.x + at.getX() * step.x, origin.y + at.getY() * step.y, origin.z + at.getZ() * step.z);
}
public Vec3d nth(int idx) {
int coordX = idx / (extent.getY() * extent.getZ());
int remX = idx % (extent.getY() * extent.getZ());
int coordY = remX / extent.getZ();
int coordZ = remX % extent.getZ();
return new Vec3d(origin.x + coordX * step.x, origin.y + coordY * step.y, origin.z + coordZ * step.z);
Vec3i coords = domain.nToGridCoordsInFrame(idx);
return new Vec3d(origin.x + coords.getX() * step.x, origin.y + coords.getY() * step.y, origin.z + coords.getZ() * step.z);
}
public Iterator<Vec3d> iterator() {
@ -72,7 +63,7 @@ public class PointGrid implements PointList {
}
public Vec3d center() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x / 2.0, origin.y + (extent.getY() - 1) * step.y / 2.0, origin.z + (extent.getZ() - 1) * step.z / 2.0);
return new Vec3d(origin.x + (domain.extent.getX() - 1) * step.x / 2.0, origin.y + (domain.extent.getY() - 1) * step.y / 2.0, origin.z + (domain.extent.getZ() - 1) * step.z / 2.0);
}
public Vec3d origin() {
@ -80,7 +71,18 @@ public class PointGrid implements PointList {
}
public Vec3d remote() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x, origin.y + (extent.getY() - 1) * step.y, origin.z + (extent.getZ() - 1) * step.z);
return new Vec3d(origin.x + (domain.extent.getX() - 1) * step.x, origin.y + (domain.extent.getY() - 1) * step.y, origin.z + (domain.extent.getZ() - 1) * step.z);
}
public PointGrid changeDomain(IntGrid newDomain) {
this.origin = getCoords(newDomain.origin());
this.domain = newDomain;
return this;
}
// intGrids will still share a reference though
public PointGrid clone() {
return new PointGrid(origin, domain, step);
}
}

16
src/main/java/t/j/dual/PointList.java

@ -1,16 +0,0 @@
package t.j.dual;
import java.util.Iterator;
import net.minecraft.util.math.*;
public interface PointList {
int numPoints();
Vec3d nth(int idx);
Vec3d center();
public Iterator<Vec3d> iterator();
// bounding box:
Vec3d origin();
Vec3d remote();
}

6
src/main/java/t/j/dual/PointWorld.java

@ -8,7 +8,7 @@ import net.minecraft.util.math.*;
import t.j.dual.Utilities;
interface PointWorld {
interface PointWorld extends SampledGrid<ArrayList<Vec3d>> {
public ArrayList<Vec3d> pointsInCell(Vec3i cell);
public float getMeanPointsPerCell();
@ -30,4 +30,8 @@ interface PointWorld {
}
return points;
}
default public ArrayList<Vec3d> get(Vec3i cell) {
return pointsInCell(cell);
}
}

13
src/main/java/t/j/dual/SampledGrid.java

@ -0,0 +1,13 @@
package t.j.dual;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public interface SampledGrid<T> {
public T get(Vec3i cell);
default public FiniteSampledGrid<T> sampleOnGrid(IntGrid grid) {
return new SlicedFiniteSampledGrid<T>(this, grid);
}
}

33
src/main/java/t/j/dual/SlicedFiniteSampledGrid.java

@ -0,0 +1,33 @@
package t.j.dual;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public class SlicedFiniteSampledGrid<T> implements FiniteSampledGrid<T> {
private IntGrid grid;
private SampledGrid<T> source;
public SlicedFiniteSampledGrid(SampledGrid<T> source, IntGrid intGrid) {
if (source instanceof SlicedFiniteSampledGrid) {
SlicedFiniteSampledGrid<T> sliced = (SlicedFiniteSampledGrid<T>) source;
this.source = sliced.source;
this.grid = sliced.grid.intersect(intGrid);
} else if (source instanceof FiniteSampledGrid) {
FiniteSampledGrid finite = (FiniteSampledGrid) source;
this.source = source;
this.grid = finite.getGrid().intersect(intGrid);
} else {
this.source = source;
this.grid = intGrid;
}
}
public IntGrid getGrid() {
return grid;
}
public T get(Vec3i cell) {
return source.get(cell);
}
}

45
src/main/java/t/j/dual/StoredFiniteSampledGrid.java

@ -0,0 +1,45 @@
package t.j.dual;
import java.util.ArrayList;
import java.util.function.Function;
import net.minecraft.util.math.*;
import t.j.dual.Utilities;
public class StoredFiniteSampledGrid<T> implements FiniteSampledGrid<T> {
private ArrayList<T> samples;
private IntGrid grid;
public StoredFiniteSampledGrid(IntGrid grid, ArrayList<T> samples) {
this.grid = grid;
this.samples = samples;
if (samples.size() != grid.numPoints()) {
Utilities.logger.warn("[StoredFiniteSampledGrid constructor] Size of grid does not match size of samples array!");
}
}
public StoredFiniteSampledGrid(PointGrid grid, Function<Vec3d, T> f) {
this.grid = grid.domain;
samples = new ArrayList<T>(grid.numPoints());
for (Vec3d coords: grid) {
samples.add(f.apply(coords));
}
}
public StoredFiniteSampledGrid(FiniteSampledGrid<T> source) {
this.grid = source.getGrid();
samples = new ArrayList<T>(grid.numPoints());
for (Vec3i coords: grid) {
samples.add(source.get(coords));
}
}
public IntGrid getGrid() {
return grid;
}
public T get(Vec3i coords) {
return samples.get(grid.gridCoordsToN(coords));
}
}

65
src/main/java/t/j/dual/Utilities.java

@ -8,6 +8,24 @@ import org.apache.logging.log4j.Logger;
class Utilities {
public static Logger logger;
// Modulus m, not remainder r. For all b > 0, a: 0 m < b
public static int iMod(int a, int b) {
if (a >= 0) {
return a % b;
} else {
return b + a % b;
}
}
// Euclidean division, q. For all a, b: qb + m = a
public static int iDiv(int a, int b) {
if (a >= 0) {
return a / b;
} else {
return a / b - 1;
}
}
public static int drawPoisson(Random random, float mean) {
float target = (float) Math.exp(-mean);
float l = 1.0f;
@ -37,6 +55,22 @@ class Utilities {
return new Vec3d(1.0 / b.x, 1.0 / b.y, 1.0 / b.z);
}
public static Vec3i viSub(Vec3i a, Vec3i b) {
return new Vec3i(a.getX() - b.getX(), a.getY() - b.getY(), a.getZ() - b.getZ());
}
public static Vec3i viAdd(Vec3i a, Vec3i b) {
return new Vec3i(a.getX() + b.getX(), a.getY() + b.getY(), a.getZ() + b.getZ());
}
public static Vec3i ewiMax(Vec3i a, Vec3i b) {
return new Vec3i(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY()), Math.max(a.getZ(), b.getZ()));
}
public static Vec3i ewiMin(Vec3i a, Vec3i b) {
return new Vec3i(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY()), Math.min(a.getZ(), b.getZ()));
}
public static class LFSRRandom extends Random {
private long seed;
@ -49,7 +83,7 @@ class Utilities {
// 63 zeros is extended to 64 zeroes. This is to (a) prevent degeneraccy
// when the LFSR's seed becomes zero; and (b) balance the number of zeroes
// and ones exactly.
public long shiftAndFeedback(long in) {
public static long shiftAndFeedback(long in) {
if ((in & 0x7fffffff) == 0) {
if (in == 0) {
return 1;
@ -81,5 +115,34 @@ class Utilities {
return trimmed;
}
}
// See arXiv:1704.00358v5, "Middle Square Weyl Sequence RNG", Bernard Widynski
public static class MiddleSquareWeylRandom extends Random {
private long seed;
private long oddConstant;
private long sequenceElement;
public MiddleSquareWeylRandom(long seed, long oddConstant) {
this.setOddConstant(oddConstant);
this.setSeed(seed);
}
public void setSeed(long seed) {
this.seed = seed;
this.sequenceElement = seed + oddConstant;
}
public void setOddConstant(long oddConstant) {
this.oddConstant = oddConstant | 1;
}
// I'm not bothering to mask out the upper bits in the hope that it will be satistactory.
protected int next(int bits) {
sequenceElement += oddConstant;
seed = seed * seed + sequenceElement;
seed = (seed >>> 32) | (seed << 32);
return (int) seed;
}
}
}
Loading…
Cancel
Save