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 io.nosqlbench.virtdata.library.curves4.discrete.common.ThreadSafeHash;
import java.util.Arrays;
import java.util.function.DoubleUnaryOperator; import java.util.function.DoubleUnaryOperator;
import java.util.function.IntToDoubleFunction; import java.util.function.IntToDoubleFunction;
@ -9,30 +10,41 @@ public class InterpolatingIntDoubleSampler implements IntToDoubleFunction{
private final double[] lut; private final double[] lut;
private final DoubleUnaryOperator f; private final DoubleUnaryOperator f;
private int resolution; private final int resolution;
private final boolean clamp; private final boolean clamp;
private final double clampMin;
private final double clampMax; private final double clampMax;
private ThreadSafeHash hash; 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.f = icdSource;
this.resolution = resolution;
this.clamp = clamp; this.clamp = clamp;
this.clampMin = clampMin;
this.clampMax = clampMax; this.clampMax = clampMax;
if (hash) { if (hash) {
this.hash = new ThreadSafeHash(); 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() { private double[] precompute(int resolution) {
double[] precomputed = new double[resolution+2]; double[] precomputed = new double[resolution+1];
for (int s = 0; s <= resolution; s++) { // not a ranging error for (int s = 0; s <= resolution; s++) { // not a ranging error
double rangedToUnit = (double) s / (double) resolution; 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[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; 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 io.nosqlbench.virtdata.library.curves4.discrete.common.ThreadSafeHash;
import java.util.Arrays;
import java.util.function.DoubleUnaryOperator; import java.util.function.DoubleUnaryOperator;
import java.util.function.LongToDoubleFunction; import java.util.function.LongToDoubleFunction;
@ -9,30 +10,41 @@ public class InterpolatingLongDoubleSampler implements LongToDoubleFunction {
private final double[] lut; private final double[] lut;
private final DoubleUnaryOperator f; private final DoubleUnaryOperator f;
private int resolution; private final int resolution;
private final boolean clamp; private final boolean clamp;
private final double clampMin;
private final double clampMax; private final double clampMax;
private ThreadSafeHash hash; 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.f = icdSource;
this.resolution = resolution;
if (hash) { if (hash) {
this.hash = new ThreadSafeHash(); this.hash = new ThreadSafeHash();
} }
this.clamp=clamp; this.clamp=clamp;
this.clampMin=clampMin;
this.clampMax=clampMax; 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() { private double[] precompute(int resolution) {
double[] precomputed = new double[resolution+2]; double[] precomputed = new double[resolution+1];
for (int s = 0; s <= resolution; s++) { // not a ranging error for (int s = 0; s <= resolution; s++) { // not a ranging error
double rangedToUnit = (double) s / (double) resolution; 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[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; return precomputed;
} }

View File

@ -63,16 +63,22 @@ import java.util.function.IntToDoubleFunction;
*/ */
public class IntToDoubleContinuousCurve implements IntToDoubleFunction { public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
private ContinuousDistribution distribution; private final ContinuousDistribution distribution;
private IntToDoubleFunction function; private final IntToDoubleFunction function;
public final static String COMPUTE="compute"; public final static String COMPUTE="compute";
public final static String INTERPOLATE="interpolate"; public final static String INTERPOLATE="interpolate";
public final static String MAP="map"; public final static String MAP="map";
public final static String HASH="hash"; public final static String HASH="hash";
public final static String CLAMP="clamp"; public final static String CLAMP="clamp";
public final static String NOCLAMP="noclamp"; 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>() {{ private final static HashSet<String> validModifiers = new HashSet<String>() {{
add(COMPUTE); add(COMPUTE);
add(INTERPOLATE); add(INTERPOLATE);
@ -80,6 +86,8 @@ public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
add(HASH); add(HASH);
add(CLAMP); add(CLAMP);
add(NOCLAMP); add(NOCLAMP);
add(INFINITE);
add(FINITE);
}}; }};
public IntToDoubleContinuousCurve(ContinuousDistribution distribution, String... modslist) { public IntToDoubleContinuousCurve(ContinuousDistribution distribution, String... modslist) {
@ -97,19 +105,24 @@ public class IntToDoubleContinuousCurve implements IntToDoubleFunction {
if (mods.contains(CLAMP) && mods.contains(NOCLAMP)) { if (mods.contains(CLAMP) && mods.contains(NOCLAMP)) {
throw new RuntimeException("mods must not contain both "+CLAMP+" and "+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) { for (String s : modslist) {
if (!validModifiers.contains(s)) { 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 hash = ( mods.contains(HASH) || !mods.contains(MAP));
boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE)); boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE));
boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP)); boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP));
boolean finite = ( mods.contains(FINITE) || !mods.contains(INFINITE));
function = interpolate ? 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); 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 { public class LongToDoubleContinuousCurve implements LongToDoubleFunction {
private ContinuousDistribution distribution; private final ContinuousDistribution distribution;
private LongToDoubleFunction function; private final LongToDoubleFunction function;
public final static String COMPUTE="compute"; public final static String COMPUTE="compute";
public final static String INTERPOLATE="interpolate"; public final static String INTERPOLATE="interpolate";
public final static String MAP="map"; public final static String MAP="map";
public final static String HASH="hash"; public final static String HASH="hash";
public final static String CLAMP="clamp"; public final static String CLAMP="clamp";
public final static String NOCLAMP="noclamp"; 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>() {{ private final static HashSet<String> validModifiers = new HashSet<String>() {{
add(COMPUTE); add(COMPUTE);
add(INTERPOLATE); add(INTERPOLATE);
@ -80,6 +85,8 @@ public class LongToDoubleContinuousCurve implements LongToDoubleFunction {
add(HASH); add(HASH);
add(CLAMP); add(CLAMP);
add(NOCLAMP); 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+"."); 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) { for (String s : modslist) {
if (!validModifiers.contains(s)) { 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 hash = ( mods.contains(HASH) || !mods.contains(MAP));
boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE)); boolean interpolate = ( mods.contains(INTERPOLATE) || !mods.contains(COMPUTE));
boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP)); boolean clamp = ( mods.contains(CLAMP) || !mods.contains(NOCLAMP));
boolean finite = ( mods.contains(FINITE) || !mods.contains(INFINITE));
function = interpolate ? 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); new RealLongDoubleSampler(icdSource, hash, clamp, (double) Long.MAX_VALUE);