diff --git a/src/jmh/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseBenchmark.java b/src/jmh/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseBenchmark.java new file mode 100644 index 0000000..7622a6b --- /dev/null +++ b/src/jmh/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseBenchmark.java @@ -0,0 +1,114 @@ +package com.dfsek.seismic.algorithms.sampler.noise.random; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +public class WhiteNoiseBenchmark { + + private WhiteNoiseSampler f; + + private long seed; + private int startX; + private int startY; + private int startZ; + + @Setup + public void setup() { + f = new WhiteNoiseSampler(123123); + + Random r = new Random(); + startX = r.nextInt(10000); + startY = r.nextInt(10000); + startZ = r.nextInt(10000); + + seed = r.nextLong(); + } + + @Benchmark + @Fork(1) + @Warmup(iterations = 5, time = 1) + @Measurement(iterations = 10, time = 5) + public double mask() { + double sum = 0.0; + + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + sum += Double.longBitsToDouble(WhiteNoiseSampler.randomBits(seed, x, z) & 0x000fffffffffffffL); + } + } + return sum; + } + + @Benchmark + @Fork(1) + @Warmup(iterations = 5, time = 1) + @Measurement(iterations = 10, time = 5) + public double shift() { + double sum = 0.0; + + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + sum += Double.longBitsToDouble(WhiteNoiseSampler.randomBits(seed, x, z) >>> 12); + } + } + return sum; + } + + @Benchmark + @Fork(1) + @Warmup(iterations = 5, time = 1) + @Measurement(iterations = 10, time = 5) + public double benchmarkWhiteNoise3D() { + double sum = 0.0; + + int sx = startX; + int sy = startY; + int sz = startZ; + long s = seed; + WhiteNoiseSampler ns = f; + + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + for(int y = 0; y < 384; y++) { + sum += ns.getSample(s, sx + x, sy + y, sz + z); + } + } + } + return sum; + } + + @Benchmark + @Fork(1) + @Warmup(iterations = 5, time = 1) + @Measurement(iterations = 10, time = 5) + public double benchmarkWhiteNoise2D() { + double sum = 0.0; + + int sx = startX; + int sy = startY; + long s = seed; + WhiteNoiseSampler ns = f; + + for(int x = 0; x < 16; x++) { + for(int y = 0; y < 16; y++) { + sum += ns.getSample(s, sx + x, sy + y); + } + } + return sum; + } +} diff --git a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/GaborSampler.java b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/GaborSampler.java index 061dd77..b76b9d4 100644 --- a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/GaborSampler.java +++ b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/GaborSampler.java @@ -40,7 +40,7 @@ public GaborSampler(double frequency, long salt, double frequency0, double devia double impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; g = Math.exp(-impulsesPerCell); - rand = new WhiteNoiseSampler(frequency, salt); + rand = new WhiteNoiseSampler(salt); } private double gaborNoise(long seed, double x, double y) { diff --git a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/GaussianNoiseSampler.java b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/GaussianNoiseSampler.java index 6426155..e29ecc8 100644 --- a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/GaussianNoiseSampler.java +++ b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/GaussianNoiseSampler.java @@ -9,21 +9,24 @@ import com.dfsek.seismic.algorithms.sampler.noise.NoiseFunction; +import com.dfsek.seismic.type.sampler.Sampler; /** * NoiseSampler implementation to provide random, normally distributed (Gaussian) noise. */ -public class GaussianNoiseSampler extends NoiseFunction { +public class GaussianNoiseSampler implements Sampler { private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler. + private final long salt; - public GaussianNoiseSampler(double frequency, long salt) { - super(frequency, salt); - whiteNoiseSampler = new WhiteNoiseSampler(frequency, salt); + public GaussianNoiseSampler(long salt) { + this.salt = salt; + whiteNoiseSampler = new WhiteNoiseSampler(0); } @Override - public double getNoiseRaw(long seed, double x, double y) { + public double getSample(long seed, double x, double y) { + seed += salt; // saves us a few adds double v1, v2, s; do { v1 = whiteNoiseSampler.getSample(seed++, x, y); @@ -35,7 +38,8 @@ public double getNoiseRaw(long seed, double x, double y) { } @Override - public double getNoiseRaw(long seed, double x, double y, double z) { + public double getSample(long seed, double x, double y, double z) { + seed += salt; // saves us a few adds double v1, v2, s; do { v1 = whiteNoiseSampler.getSample(seed++, x, y, z); diff --git a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/PositiveWhiteNoiseSampler.java b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/PositiveWhiteNoiseSampler.java index cedc6d6..69d8253 100644 --- a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/PositiveWhiteNoiseSampler.java +++ b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/PositiveWhiteNoiseSampler.java @@ -16,24 +16,38 @@ */ public class PositiveWhiteNoiseSampler extends WhiteNoiseSampler { private static final long POSITIVE_POW1 = 0b01111111111L << 52; + private final long salt; - public PositiveWhiteNoiseSampler(double frequency, long salt) { - super(frequency, salt); + public PositiveWhiteNoiseSampler(long salt) { + super(salt); + this.salt = salt; } // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. + public static double getNoiseUnmapped(long seed, double x, double y, double z) { + long base = ((WhiteNoiseSampler.randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | + POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + public static double getNoiseUnmapped(long seed, double x, double y) { + long base = (WhiteNoiseSampler.randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + @Override public double getNoiseRaw(long seed) { - return (Double.longBitsToDouble((HashingFunctions.murmur64(seed) & 0x000fffffffffffffL) | PositiveWhiteNoiseSampler.POSITIVE_POW1) - - 1.5) * 2; + return (Double.longBitsToDouble((HashingFunctions.murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - + 1); } @Override - public double getNoiseRaw(long seed, double x, double y) { - return (WhiteNoiseSampler.getNoiseUnmapped(seed, x, y) - 1); + public double getSample(long seed, double x, double y) { + return (getNoiseUnmapped(seed + salt, x, y) - 1); } @Override - public double getNoiseRaw(long seed, double x, double y, double z) { - return (WhiteNoiseSampler.getNoiseUnmapped(seed, x, y, z) - 1); + public double getSample(long seed, double x, double y, double z) { + return (getNoiseUnmapped(seed + salt, x, y, z) - 1); } } diff --git a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseSampler.java b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseSampler.java index 2a4d212..29b65dd 100644 --- a/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseSampler.java +++ b/src/main/java/com/dfsek/seismic/algorithms/sampler/noise/random/WhiteNoiseSampler.java @@ -9,17 +9,19 @@ import com.dfsek.seismic.algorithms.hashing.HashingFunctions; import com.dfsek.seismic.algorithms.sampler.noise.NoiseFunction; +import com.dfsek.seismic.type.sampler.Sampler; /** * NoiseSampler implementation to produce random, uniformly distributed (white) noise. */ -public class WhiteNoiseSampler extends NoiseFunction { - private static final long POSITIVE_POW1 = 0b01111111111L << 52; +public class WhiteNoiseSampler implements Sampler { + private static final long POSITIVE_POW1 = 0b10000000000L << 52; + private final long salt; // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. - public WhiteNoiseSampler(double frequency, long salt) { - super(frequency, salt); + public WhiteNoiseSampler(long salt) { + this.salt = salt; } public static long randomBits(long seed, double x, double y, double z) { @@ -38,27 +40,26 @@ public static long randomBits(long seed, double x, double y) { public static double getNoiseUnmapped(long seed, double x, double y, double z) { long base = ((WhiteNoiseSampler.randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | - WhiteNoiseSampler.POSITIVE_POW1; // Sign and exponent + POSITIVE_POW1; // Sign and exponent return Double.longBitsToDouble(base); } public static double getNoiseUnmapped(long seed, double x, double y) { - long base = (WhiteNoiseSampler.randomBits(seed, x, y) & 0x000fffffffffffffL) | WhiteNoiseSampler.POSITIVE_POW1; // Sign and exponent + long base = (WhiteNoiseSampler.randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent return Double.longBitsToDouble(base); } public double getNoiseRaw(long seed) { - return (Double.longBitsToDouble((HashingFunctions.murmur64(seed) & 0x000fffffffffffffL) | WhiteNoiseSampler.POSITIVE_POW1) - 1.5) * - 2; + return Double.longBitsToDouble((HashingFunctions.murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 3; } @Override - public double getNoiseRaw(long seed, double x, double y) { - return (WhiteNoiseSampler.getNoiseUnmapped(seed, x, y) - 1.5) * 2; + public double getSample(long seed, double x, double y) { + return WhiteNoiseSampler.getNoiseUnmapped(seed + salt, x, y) - 3; } @Override - public double getNoiseRaw(long seed, double x, double y, double z) { - return (WhiteNoiseSampler.getNoiseUnmapped(seed, x, y, z) - 1.5) * 2; + public double getSample(long seed, double x, double y, double z) { + return (WhiteNoiseSampler.getNoiseUnmapped(seed + salt, x, y, z) - 1.5) * 2; } }