support +-Infinity suppression, and int or long value clamping in distribution functions

This commit is contained in:
Jonathan Shook 2021-11-12 19:56:57 -06:00
parent 79547218df
commit 5332264813
4 changed files with 73 additions and 24 deletions

View File

@ -2,6 +2,7 @@ package io.nosqlbench.virtdata.library.curves4.continuous.common;
import io.nosqlbench.virtdata.library.curves4.discrete.common.ThreadSafeHash;
import java.util.Arrays;
import java.util.function.DoubleUnaryOperator;
import java.util.function.IntToDoubleFunction;
@ -9,30 +10,41 @@ public class InterpolatingIntDoubleSampler implements IntToDoubleFunction{
private final double[] lut;
private final DoubleUnaryOperator f;
private int resolution;
private final int resolution;
private final boolean clamp;
private final double clampMin;
private final double clampMax;
private ThreadSafeHash hash;
public InterpolatingIntDoubleSampler(DoubleUnaryOperator icdSource, int resolution, boolean hash, boolean clamp, double clampMax) {
public InterpolatingIntDoubleSampler(DoubleUnaryOperator icdSource, int resolution, boolean hash, boolean clamp, double clampMin, double clampMax, boolean finite) {
this.f = icdSource;
this.resolution = resolution;
this.clamp = clamp;
this.clampMin = clampMin;
this.clampMax = clampMax;
if (hash) {
this.hash = new ThreadSafeHash();
}
this.lut = precompute();
double[] lut = precompute(resolution);
if (finite) {
while (lut.length>0 && Double.isInfinite(lut[0])) {
lut = Arrays.copyOfRange(lut,1,lut.length-1);
}
while (lut.length>0 && Double.isInfinite(lut[lut.length-1])) {
lut = Arrays.copyOfRange(lut,0,lut.length-2);
}
}
this.lut = lut;
this.resolution=lut.length-1;
}
private double[] precompute() {
double[] precomputed = new double[resolution+2];
private double[] precompute(int resolution) {
double[] precomputed = new double[resolution+1];
for (int s = 0; s <= resolution; s++) { // not a ranging error
double rangedToUnit = (double) s / (double) resolution;
double sampleValue = clamp ? Double.min(clampMax,f.applyAsDouble(rangedToUnit)) : f.applyAsDouble(rangedToUnit);
double sampleValue = clamp ? Double.max(clampMin,Double.min(clampMax,f.applyAsDouble(rangedToUnit))) : f.applyAsDouble(rangedToUnit);
precomputed[s] = sampleValue;
}
precomputed[precomputed.length-1]=0.0D; // only for right of max, when S==Max in the rare case
precomputed[precomputed.length-1]=precomputed[precomputed.length-2]; // only for right of max, when S==Max in the rare case
return precomputed;
}

View File

@ -2,6 +2,7 @@ package io.nosqlbench.virtdata.library.curves4.continuous.common;
import io.nosqlbench.virtdata.library.curves4.discrete.common.ThreadSafeHash;
import java.util.Arrays;
import java.util.function.DoubleUnaryOperator;
import java.util.function.LongToDoubleFunction;
@ -9,30 +10,41 @@ public class InterpolatingLongDoubleSampler implements LongToDoubleFunction {
private final double[] lut;
private final DoubleUnaryOperator f;
private int resolution;
private final int resolution;
private final boolean clamp;
private final double clampMin;
private final double clampMax;
private ThreadSafeHash hash;
public InterpolatingLongDoubleSampler(DoubleUnaryOperator icdSource, int resolution, boolean hash, boolean clamp, double clampMax) {
public InterpolatingLongDoubleSampler(DoubleUnaryOperator icdSource, int resolution, boolean hash, boolean clamp, double clampMin, double clampMax, boolean finite) {
this.f = icdSource;
this.resolution = resolution;
if (hash) {
this.hash = new ThreadSafeHash();
}
this.clamp=clamp;
this.clampMin=clampMin;
this.clampMax=clampMax;
this.lut = precompute();
double[] lut = precompute(resolution);
if (finite) {
while (lut.length>0 && Double.isInfinite(lut[0])) {
lut = Arrays.copyOfRange(lut,1,lut.length-1);
}
while (lut.length>0 && Double.isInfinite(lut[lut.length-1])) {
lut = Arrays.copyOfRange(lut,0,lut.length-2);
}
}
this.lut = lut;
this.resolution = lut.length-1;
}
private double[] precompute() {
double[] precomputed = new double[resolution+2];
private double[] precompute(int resolution) {
double[] precomputed = new double[resolution+1];
for (int s = 0; s <= resolution; s++) { // not a ranging error
double rangedToUnit = (double) s / (double) resolution;
double sampleValue = clamp ? Double.min(clampMax,f.applyAsDouble(rangedToUnit)) : f.applyAsDouble(rangedToUnit);
double sampleValue = clamp ? Double.max(clampMin,Double.min(clampMax,f.applyAsDouble(rangedToUnit))) : f.applyAsDouble(rangedToUnit);
precomputed[s] = sampleValue;
}
precomputed[precomputed.length-1]=0.0D; // only for right of max, when S==Max in the rare case
precomputed[precomputed.length-1]=precomputed[precomputed.length-2]; // only for right of max, when S==Max in the rare case
return precomputed;
}

View File

@ -63,16 +63,22 @@ import java.util.function.IntToDoubleFunction;
*/
public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
private ContinuousDistribution distribution;
private IntToDoubleFunction function;
private final ContinuousDistribution distribution;
private final IntToDoubleFunction function;
public final static String COMPUTE="compute";
public final static String INTERPOLATE="interpolate";
public final static String MAP="map";
public final static String HASH="hash";
public final static String CLAMP="clamp";
public final static String NOCLAMP="noclamp";
public final static String INFINITE ="infinite";
public final static String FINITE = "finite";
private final static HashSet<String> validModifiers = new HashSet<String>() {{
add(COMPUTE);
add(INTERPOLATE);
@ -80,6 +86,8 @@ public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
add(HASH);
add(CLAMP);
add(NOCLAMP);
add(INFINITE);
add(FINITE);
}};
public IntToDoubleContinuousCurve(ContinuousDistribution distribution, String... modslist) {
@ -97,19 +105,24 @@ public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
if (mods.contains(CLAMP) && mods.contains(NOCLAMP)) {
throw new RuntimeException("mods must not contain both "+CLAMP+" and "+NOCLAMP+".");
}
if (mods.contains(INFINITE) && mods.contains(FINITE)) {
throw new RuntimeException("mods must not contain both "+ INFINITE +" and "+FINITE+".");
}
for (String s : modslist) {
if (!validModifiers.contains(s)) {
throw new RuntimeException("modifier '" + s + "' is not a valid modifier. Use one of " + validModifiers.toString() + " instead.");
throw new RuntimeException("modifier '" + s + "' is not a valid modifier. Use one of " + validModifiers + " instead.");
}
}
boolean hash = ( mods.contains(HASH) || !mods.contains(MAP));
boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE));
boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP));
boolean finite = ( mods.contains(FINITE) || !mods.contains(INFINITE));
function = interpolate ?
new InterpolatingIntDoubleSampler(icdSource, 1000, hash, clamp, (double) Long.MAX_VALUE)
new InterpolatingIntDoubleSampler(icdSource, 1000, hash, clamp, Integer.MIN_VALUE, Long.MAX_VALUE, finite)
:
new RealIntDoubleSampler(icdSource, hash, clamp, (double) Long.MAX_VALUE);

View File

@ -63,16 +63,21 @@ import java.util.function.LongToDoubleFunction;
*/
public class LongToDoubleContinuousCurve implements LongToDoubleFunction {
private ContinuousDistribution distribution;
private LongToDoubleFunction function;
private final ContinuousDistribution distribution;
private final LongToDoubleFunction function;
public final static String COMPUTE="compute";
public final static String INTERPOLATE="interpolate";
public final static String MAP="map";
public final static String HASH="hash";
public final static String CLAMP="clamp";
public final static String NOCLAMP="noclamp";
public final static String INFINITE ="infinite";
public final static String FINITE = "finite";
private final static HashSet<String> validModifiers = new HashSet<String>() {{
add(COMPUTE);
add(INTERPOLATE);
@ -80,6 +85,8 @@ public class LongToDoubleContinuousCurve implements LongToDoubleFunction {
add(HASH);
add(CLAMP);
add(NOCLAMP);
add(INFINITE);
add(FINITE);
}};
@ -99,18 +106,23 @@ public class LongToDoubleContinuousCurve implements LongToDoubleFunction {
throw new RuntimeException("mods must not contain both "+CLAMP+" and "+NOCLAMP+".");
}
if (mods.contains(INFINITE) && mods.contains(FINITE)) {
throw new RuntimeException("mods must not contain both "+ INFINITE +" and "+FINITE+".");
}
for (String s : modslist) {
if (!validModifiers.contains(s)) {
throw new RuntimeException("modifier '" + s + "' is not a valid modifier. Use one of " + validModifiers.toString() + " instead.");
throw new RuntimeException("modifier '" + s + "' is not a valid modifier. Use one of " + validModifiers + " instead.");
}
}
boolean hash = ( mods.contains(HASH) || !mods.contains(MAP));
boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE));
boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP));
boolean finite = ( mods.contains(FINITE) || !mods.contains(INFINITE));
function = interpolate ?
new InterpolatingLongDoubleSampler(icdSource, 1000, hash, clamp, (double) Long.MAX_VALUE)
new InterpolatingLongDoubleSampler(icdSource, 1000, hash, clamp, Long.MIN_VALUE, Long.MAX_VALUE, finite)
:
new RealLongDoubleSampler(icdSource, hash, clamp, (double) Long.MAX_VALUE);