Add unit tests for spatial indexing and random number generation utilities
This commit is contained in:
@@ -0,0 +1,116 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.spatial2;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.extio.game_engine.spatial2.model.Area2;
|
||||||
|
import de.extio.game_engine.spatial2.model.CoordD2;
|
||||||
|
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.Edge2;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.MutableCoordD2;
|
||||||
|
|
||||||
|
public class WorldUtils2Tests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVectorAngle() {
|
||||||
|
CoordD2 v0 = MutableCoordD2.create(0.0, 0.0);
|
||||||
|
CoordD2 v1 = MutableCoordD2.create(0.0, 0.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(0.0, 0.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(0.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(-1.0, 0.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(0.5, 0.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(-1.0, 0.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(-1.0, 1.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(-0.5, 1.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(-1.0, 5.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(1.0, 0.0);
|
||||||
|
v1 = MutableCoordD2.create(0.0, -1.0);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
|
||||||
|
v0 = MutableCoordD2.create(-0.31617965644035745, 0.21078643762690494);
|
||||||
|
v1 = MutableCoordD2.create(-0.29595508588991065, 0.19730339059327376);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVectorAngle2() {
|
||||||
|
for (double i = -1.0; i < 1.0; i += 0.2) {
|
||||||
|
for (double ii = -1.0; ii < 1.0; ii += 0.2) {
|
||||||
|
final CoordD2 v0 = MutableCoordD2.create(i, ii);
|
||||||
|
final CoordD2 v1 = MutableCoordD2.create(ii, i);
|
||||||
|
this.calcAngle(v0, v1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWorldUtils2PointsToArea() {
|
||||||
|
final CoordI2 point0 = ImmutableCoordI2.create(6, 8);
|
||||||
|
final CoordI2 point1 = ImmutableCoordI2.create(6, 9);
|
||||||
|
assertEquals(ImmutableCoordI2.create(6, 8), WorldUtils2.pointsToArea(point0, point1).getPosition());
|
||||||
|
assertEquals(ImmutableCoordI2.create(1, 2), WorldUtils2.pointsToArea(point0, point1).getDimension());
|
||||||
|
assertEquals(ImmutableCoordI2.create(6, 8), WorldUtils2.pointsToArea(point1, point0).getPosition());
|
||||||
|
assertEquals(ImmutableCoordI2.create(1, 2), WorldUtils2.pointsToArea(point1, point0).getDimension());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointInCircle() {
|
||||||
|
for (double n = -Math.PI; n < Math.PI; n += 0.1) {
|
||||||
|
System.out.println(n + " " + Math.cos(n) + " " + Math.sin(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSector() {
|
||||||
|
final Area2 area = new Area2(ImmutableCoordI2.create(100, 100), ImmutableCoordI2.create(20, 20));
|
||||||
|
|
||||||
|
assertEquals(Edge2.RIGHT, WorldUtils2.getSector(ImmutableCoordI2.create(120, 110), area));
|
||||||
|
assertEquals(Edge2.LEFT, WorldUtils2.getSector(ImmutableCoordI2.create(105, 110), area));
|
||||||
|
assertEquals(Edge2.TOP, WorldUtils2.getSector(ImmutableCoordI2.create(110, 100), area));
|
||||||
|
assertEquals(Edge2.BOTTOM, WorldUtils2.getSector(ImmutableCoordI2.create(110, 120), area));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPedalNaN() {
|
||||||
|
final CoordD2 result = WorldUtils2.getPedalOnLineSegmentAB(ImmutableCoordI2.create(-802, -905), ImmutableCoordI2.create(-805, -887), ImmutableCoordI2.create(-804, -893));
|
||||||
|
assertNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calcAngle(final CoordD2 v0, final CoordD2 v1) {
|
||||||
|
System.out.println(WorldUtils2.getVectorAngle(v0, v1) + " " + v0 + " " + v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Stephan Birkl - All Rights Reserved. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.spatial2.index;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.extio.game_engine.spatial2.model.Area2;
|
||||||
|
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.SpatialIndex2Capable;
|
||||||
|
import de.extio.game_engine.util.rng.XorShift128Random;
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
public class QuadTreeTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeDim1Inserts() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int x = 0; x < 100; x++) {
|
||||||
|
for (int y = 0; y < 100; y++) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(x, y), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < 100; x++) {
|
||||||
|
for (int y = 0; y < 100; y++) {
|
||||||
|
final TestEntity entity = index.find(ImmutableCoordI2.create(x, y), ImmutableCoordI2.one()).get(0);
|
||||||
|
assertEquals(x, entity.getPosition().getX());
|
||||||
|
assertEquals(y, entity.getPosition().getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeNDimInserts() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int i = 10; i < 300; i += 20) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i)));
|
||||||
|
}
|
||||||
|
for (int i = 290; i > 0; i -= 20) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i)));
|
||||||
|
}
|
||||||
|
for (int i = 15; i < 300; i += 10) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 10; i < 300; i += 20) {
|
||||||
|
final List<TestEntity> objs = index.find(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i));
|
||||||
|
final int iF = i;
|
||||||
|
assertTrue(objs.stream().anyMatch(e -> e.getPosition().getX() == iF), String.valueOf(i));
|
||||||
|
}
|
||||||
|
for (int i = 290; i > 0; i -= 20) {
|
||||||
|
final List<TestEntity> objs = index.find(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i));
|
||||||
|
final int iF = i;
|
||||||
|
assertTrue(objs.stream().anyMatch(e -> e.getPosition().getX() == iF), String.valueOf(i));
|
||||||
|
}
|
||||||
|
for (int i = 15; i < 300; i += 10) {
|
||||||
|
final List<TestEntity> objs = index.find(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.create(i, i));
|
||||||
|
final int iF = i;
|
||||||
|
assertTrue(objs.stream().anyMatch(e -> e.getPosition().getX() == iF), String.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRandomEntities() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
final Random random = new XorShift128Random(42);
|
||||||
|
|
||||||
|
final List<TestEntity> testEntities = new ArrayList<>(100);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
testEntities.add(new TestEntity(ImmutableCoordI2.create(random.nextInt(1000), random.nextInt(1000)), ImmutableCoordI2.create(random.nextInt(29) + 1, random.nextInt(29) + 1)));
|
||||||
|
index.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final TestEntity subject = testEntities.get(i);
|
||||||
|
final List<TestEntity> objs = index.find(subject);
|
||||||
|
this.checkForDuplicates(objs);
|
||||||
|
assertTrue(!objs.isEmpty(), String.valueOf(i));
|
||||||
|
assertTrue(objs.stream().anyMatch(e -> e == subject));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final TestEntity subject = testEntities.get(i);
|
||||||
|
for (int x = subject.getPosition().getX(); x < subject.getPosition().getX() + subject.getDimension().getX(); x++) {
|
||||||
|
for (int y = subject.getPosition().getY(); y < subject.getPosition().getY() + subject.getDimension().getY(); y++) {
|
||||||
|
final List<TestEntity> objs = index.find(ImmutableCoordI2.create(x, y), ImmutableCoordI2.one());
|
||||||
|
assertTrue(!objs.isEmpty(), String.valueOf(i));
|
||||||
|
assertTrue(objs.stream().anyMatch(e -> e == subject), String.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<TestEntity> testEntitiesForEach = new ArrayList<>(100);
|
||||||
|
index.forEach(testEntitiesForEach::add);
|
||||||
|
this.checkForDuplicates(testEntitiesForEach);
|
||||||
|
assertEquals(testEntities.size(), testEntitiesForEach.size());
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final TestEntity entity = testEntities.get(i);
|
||||||
|
assertTrue(testEntitiesForEach.contains(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<TestEntity> testEntitiesIterator = new ArrayList<>(100);
|
||||||
|
final Iterator<TestEntity> it = index.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
testEntitiesIterator.add(it.next());
|
||||||
|
}
|
||||||
|
this.checkForDuplicates(testEntitiesIterator);
|
||||||
|
assertEquals(testEntities.size(), testEntitiesIterator.size());
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final TestEntity entity = testEntities.get(i);
|
||||||
|
assertTrue(testEntitiesIterator.contains(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForDuplicates(final List<TestEntity> in) {
|
||||||
|
final List<TestEntity> entities = new ArrayList<>(in);
|
||||||
|
entities.sort((e0, e1) -> Integer.compare(e0.hashCode(), e1.hashCode()));
|
||||||
|
for (int i = 1; i < entities.size(); i++) {
|
||||||
|
if (entities.get(i - 1).equals(entities.get(i))) {
|
||||||
|
fail("Duplicate " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeDim1LinearInserts() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int i = 1; i < 50; i++) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
for (int i = 0; i >= -50; i--) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = -50; i < 50; i++) {
|
||||||
|
final TestEntity entity = index.find(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()).get(0);
|
||||||
|
assertEquals(i, entity.getPosition().getX());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeAddRemoveAdd() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
final List<TestEntity> testEntities = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
testEntities.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
index.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
index.remove(testEntities.get(0));
|
||||||
|
index.add(testEntities.get(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
final List<TestEntity> result = index.find(testEntities.get(0).getPosition(), testEntities.get(0).getDimension());
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals(testEntities.get(0).getPosition().getX(), result.get(0).getPosition().getX());
|
||||||
|
assertEquals(testEntities.get(0).getPosition().getY(), result.get(0).getPosition().getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeRemove() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
final List<TestEntity> testEntities = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
testEntities.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
index.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
index.remove(testEntities.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQueryOutsideRange() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(50, index.find(new Area2(ImmutableCoordI2.create(0, 0), ImmutableCoordI2.create(50, 1))).size());
|
||||||
|
assertEquals(50, index.find(new Area2(ImmutableCoordI2.create(-10, 0), ImmutableCoordI2.create(100, 1))).size());
|
||||||
|
assertEquals(25, index.find(new Area2(ImmutableCoordI2.create(25, 0), ImmutableCoordI2.create(50, 1))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(-10, 0), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(100, 0), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueryOutsideRange2() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(i, 0), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(50, index.find(new Area2(ImmutableCoordI2.create(-100000, -100000), ImmutableCoordI2.create(200000, 200000))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(-100000, 0), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(100000, 0), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(0, -100000), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
assertEquals(0, index.find(new Area2(ImmutableCoordI2.create(0, 100000), ImmutableCoordI2.create(5, 1))).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeExpansion() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
for (int x = 0; x < 100000; x += 1000) {
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(x, x), ImmutableCoordI2.one()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < 100000; x += 1000) {
|
||||||
|
final TestEntity entity = index.find(ImmutableCoordI2.create(x, x), ImmutableCoordI2.one()).get(0);
|
||||||
|
assertEquals(x, entity.getPosition().getX());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadTreeExpansion2() {
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(1000, 0), ImmutableCoordI2.one()));
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(900, -5000), ImmutableCoordI2.create(1, 10000)));
|
||||||
|
index.add(new TestEntity(ImmutableCoordI2.create(-50000, -50000), ImmutableCoordI2.create(100000, 100000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
@Test
|
||||||
|
public void testCompareToSearchIndexes() {
|
||||||
|
final int SIZE = 100000;
|
||||||
|
final Random random = new XorShift128Random(42);
|
||||||
|
final SpatialIndex2D<TestEntity> quadTree = new QuadTree<>();
|
||||||
|
final SpatialIndex2D<TestEntity> linear = new LinearSearchIndex2D<>();
|
||||||
|
|
||||||
|
final List<TestEntity> testEntities = new ArrayList<>(SIZE);
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
testEntities.add(new TestEntity(ImmutableCoordI2.create(random.nextInt(10000) + 1, random.nextInt(10000) + 1), ImmutableCoordI2.create(random.nextInt(29) + 1, random.nextInt(29) + 1)));
|
||||||
|
}
|
||||||
|
final List<Area2> queries = new ArrayList<>(SIZE);
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
queries.add(new Area2(ImmutableCoordI2.create(random.nextInt(10000), random.nextInt(10000)), ImmutableCoordI2.create(random.nextInt(499) + 1, random.nextInt(499) + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
quadTree.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
System.out.println("QT add took " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
linear.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
System.out.println("LINEAR add took " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
|
||||||
|
long totalQT = 0;
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
final List<TestEntity> qtResult = quadTree.find(area);
|
||||||
|
totalQT += qtResult.size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried QT " + totalQT + " entities in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
|
||||||
|
long totalLinear = 0;
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
final List<TestEntity> bsResult = linear.find(area);
|
||||||
|
totalLinear += bsResult.size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried LINEAR " + totalLinear + " entities in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
|
||||||
|
if (totalQT != totalLinear) {
|
||||||
|
System.out.println("Error!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEntity implements SpatialIndex2Capable {
|
||||||
|
|
||||||
|
CoordI2 position;
|
||||||
|
|
||||||
|
CoordI2 dimension;
|
||||||
|
|
||||||
|
transient long bsi2Session;
|
||||||
|
|
||||||
|
public TestEntity(final CoordI2 position, final CoordI2 dimension) {
|
||||||
|
this.position = position;
|
||||||
|
this.dimension = dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoordI2 getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoordI2 getDimension() {
|
||||||
|
return this.dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInSpatialIndex2ResultSet(final long session) {
|
||||||
|
return this.bsi2Session == session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void includeInSpatialIndex2ResultSet(final long session) {
|
||||||
|
this.bsi2Session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("TestEntity [position=");
|
||||||
|
builder.append(this.position);
|
||||||
|
builder.append(", dimension=");
|
||||||
|
builder.append(this.dimension);
|
||||||
|
builder.append("]");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.spatial2.index;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.extio.game_engine.spatial2.model.Area2;
|
||||||
|
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.MutableCoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.SpatialIndex2Capable;
|
||||||
|
import de.extio.game_engine.util.rng.XorShift128Random;
|
||||||
|
|
||||||
|
public class SpatialIndex2DTests {
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
@Test
|
||||||
|
public void testQuadTreePerformance() {
|
||||||
|
System.out.println("---");
|
||||||
|
System.out.println("testQuadTreePerformance");
|
||||||
|
|
||||||
|
final SpatialIndex2D<TestEntity> index = new QuadTree<>();
|
||||||
|
this.doTestPerformance(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
@Test
|
||||||
|
public void testLinearPerformance() {
|
||||||
|
System.out.println("---");
|
||||||
|
System.out.println("testLinearPerformance");
|
||||||
|
|
||||||
|
final SpatialIndex2D<TestEntity> index = new LinearSearchIndex2D<>();
|
||||||
|
this.doTestPerformance(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doTestPerformance(final SpatialIndex2D<TestEntity> index) {
|
||||||
|
final int SIZE = 100000;
|
||||||
|
|
||||||
|
final Random random = new XorShift128Random(42);
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000l);
|
||||||
|
}
|
||||||
|
catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add
|
||||||
|
|
||||||
|
final List<TestEntity> testEntities = new ArrayList<>(SIZE);
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
testEntities.add(new TestEntity(MutableCoordI2.create(random.nextInt(10000), random.nextInt(10000)), ImmutableCoordI2.create(random.nextInt(29) + 1, random.nextInt(29) + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
index.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
System.out.println("Add " + SIZE + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Query
|
||||||
|
|
||||||
|
final List<Area2> queries = new ArrayList<>(SIZE);
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
queries.add(new Area2(ImmutableCoordI2.create(random.nextInt(10000), random.nextInt(10000)), ImmutableCoordI2.create(random.nextInt(499) + 1, random.nextInt(499) + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
long total = 0;
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
total += index.find(area).size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried " + total + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Move
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
final CoordI2 oldPosition = MutableCoordI2.create();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final TestEntity entity = testEntities.get(i);
|
||||||
|
oldPosition.setXY(entity.getPosition());
|
||||||
|
entity.getPosition().add(1);
|
||||||
|
|
||||||
|
index.move(testEntities.get(i), oldPosition, entity.getDimension());
|
||||||
|
}
|
||||||
|
System.out.println("Moved all entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Query
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
total = 0;
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
total += index.find(area).size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried " + total + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Remove
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
final int cntDelete = SIZE / 2;
|
||||||
|
for (int i = 0; i < cntDelete; i++) {
|
||||||
|
index.remove(testEntities.get(i));
|
||||||
|
}
|
||||||
|
System.out.println("Removed " + cntDelete + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Query
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
total = 0;
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
total += index.find(area).size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried " + total + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Clear
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
index.clear();
|
||||||
|
System.out.println("Clear all entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Add
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
index.add(testEntities.get(i));
|
||||||
|
}
|
||||||
|
System.out.println("Add " + SIZE + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
// Query
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
total = 0;
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
final Area2 area = queries.get(i);
|
||||||
|
total += index.find(area).size();
|
||||||
|
}
|
||||||
|
System.out.println("Queried " + total + " entities: " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
System.gc();
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000l);
|
||||||
|
}
|
||||||
|
catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEntity implements SpatialIndex2Capable {
|
||||||
|
|
||||||
|
CoordI2 position;
|
||||||
|
|
||||||
|
CoordI2 dimension;
|
||||||
|
|
||||||
|
transient long bsi2Session;
|
||||||
|
|
||||||
|
public TestEntity(final CoordI2 position, final CoordI2 dimension) {
|
||||||
|
this.position = position;
|
||||||
|
this.dimension = dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoordI2 getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoordI2 getDimension() {
|
||||||
|
return this.dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInSpatialIndex2ResultSet(final long session) {
|
||||||
|
return this.bsi2Session == session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void includeInSpatialIndex2ResultSet(final long session) {
|
||||||
|
this.bsi2Session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.util.rng;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class JavaReferenceRandomTests {
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
@Test
|
||||||
|
public void testReferenceRandom() {
|
||||||
|
final Random random = new Random(42);
|
||||||
|
|
||||||
|
System.out.println("nextDouble()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextDouble());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt(5)");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt(5));
|
||||||
|
}
|
||||||
|
System.out.println("nextLong()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextLong());
|
||||||
|
}
|
||||||
|
System.out.println("nextBoolean()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance:");
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
long a = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
a = a + random.nextLong();
|
||||||
|
}
|
||||||
|
System.out.println(a + " " + (System.currentTimeMillis() - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.util.rng;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class JavaThreadLocalRandomTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceRandom() {
|
||||||
|
final Random random = ThreadLocalRandom.current();
|
||||||
|
|
||||||
|
System.out.println("nextDouble()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextDouble());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt(5)");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt(5));
|
||||||
|
}
|
||||||
|
System.out.println("nextLong()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextLong());
|
||||||
|
}
|
||||||
|
System.out.println("nextBoolean()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance longs:");
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
long a = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
a = a + random.nextLong();
|
||||||
|
}
|
||||||
|
System.out.println(a + " " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance ints:");
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
int b = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
b = b + random.nextInt();
|
||||||
|
}
|
||||||
|
System.out.println(b + " " + (System.currentTimeMillis() - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.util.rng;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class XorShift128RandomTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testXorShift128Random() {
|
||||||
|
final Random random = new XorShift128Random(42);
|
||||||
|
|
||||||
|
System.out.println("nextDouble()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextDouble());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt(5)");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextInt(5));
|
||||||
|
}
|
||||||
|
System.out.println("nextLong()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextLong());
|
||||||
|
}
|
||||||
|
System.out.println("nextBoolean()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance longs:");
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
long a = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
a = a + random.nextLong();
|
||||||
|
}
|
||||||
|
System.out.println(a + " " + (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance ints:");
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
int b = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
b = b + random.nextInt();
|
||||||
|
}
|
||||||
|
System.out.println(b + " " + (System.currentTimeMillis() - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testXorShift128RandomSeed0() {
|
||||||
|
final Random random = new XorShift128Random(0);
|
||||||
|
|
||||||
|
System.out.println("nextDouble()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(random.nextDouble());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testXorShift128RandomIntRange() {
|
||||||
|
final Random random = new XorShift128Random(777);
|
||||||
|
|
||||||
|
for (int i = 1; i < 10; i++) {
|
||||||
|
for (int ii = 0; ii < 10; ii++) {
|
||||||
|
System.out.println(i + " " + ii + " random.nextInt(i): " + random.nextInt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testXorShift128RandomDoubleRange() {
|
||||||
|
final Random random = new XorShift128Random();
|
||||||
|
|
||||||
|
final int[] buckets = new int[1000];
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000000; i++) {
|
||||||
|
final double n = random.nextDouble();
|
||||||
|
final int bucket = (int) Math.floor(n / 0.001);
|
||||||
|
buckets[bucket]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
System.out.println(String.format("%03d", i) + " " + buckets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright (C) 2023 Stephan Birkl - All Rights Reserved.
|
||||||
|
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.extio.game_engine.util.rng;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class ZeroRandomTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSpeedRunRandom() {
|
||||||
|
final Random speedRunRandom = new ZeroRandom();
|
||||||
|
|
||||||
|
System.out.println("nextDouble()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(speedRunRandom.nextDouble());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(speedRunRandom.nextInt());
|
||||||
|
}
|
||||||
|
System.out.println("nextInt(5)");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(speedRunRandom.nextInt(5));
|
||||||
|
}
|
||||||
|
System.out.println("nextLong()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(speedRunRandom.nextLong());
|
||||||
|
}
|
||||||
|
System.out.println("nextBoolean()");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println(speedRunRandom.nextBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Performance:");
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
long a = 5;
|
||||||
|
for (int i = 0; i < 1000000000; i++) {
|
||||||
|
a = a + speedRunRandom.nextLong();
|
||||||
|
}
|
||||||
|
System.out.println(a + " " + (System.currentTimeMillis() - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user