Merge branch 'main' into dependabot/maven/mvn-defaults/io.netty-netty-handler-4.1.118.Final

This commit is contained in:
Jonathan Shook 2025-02-19 06:21:56 -06:00 committed by GitHub
commit 3458a8eac1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1154 additions and 145 deletions

View File

@ -178,17 +178,17 @@
<dependency> <dependency>
<groupId>org.apache.cassandra</groupId> <groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-core</artifactId> <artifactId>java-driver-core</artifactId>
<version>4.18.1</version> <version>4.19.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.cassandra</groupId> <groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-query-builder</artifactId> <artifactId>java-driver-query-builder</artifactId>
<version>4.18.1</version> <version>4.19.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.cassandra</groupId> <groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-mapper-runtime</artifactId> <artifactId>java-driver-mapper-runtime</artifactId>
<version>4.18.1</version> <version>4.19.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>

View File

@ -59,13 +59,11 @@
<dependency> <dependency>
<groupId>org.apache.cassandra</groupId> <groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-core</artifactId> <artifactId>java-driver-core</artifactId>
<version>4.18.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.cassandra</groupId> <groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-query-builder</artifactId> <artifactId>java-driver-query-builder</artifactId>
<version>4.18.1</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -28,33 +28,35 @@ import java.util.List;
import java.util.function.Function; import java.util.function.Function;
/** /**
* Normalize a vector in List<Number> form, calling the appropriate conversion function Normalize a vector in List<Number> form, calling the appropriate conversion function
* depending on the component (Class) type of the incoming List values. depending on the component (Class) type of the incoming List values. */
*/
@ThreadSafeMapper @ThreadSafeMapper
@Categories(Category.experimental) @Categories(Category.experimental)
public class NormalizeCqlVector implements Function<CqlVector, CqlVector> { public class NormalizeCqlVector<N extends Number> implements Function<CqlVector<N>, CqlVector<N>> {
private final NormalizeDoubleListVector ndv = new NormalizeDoubleListVector(); private final NormalizeDoubleListVector ndv = new NormalizeDoubleListVector();
private final NormalizeFloatListVector nfv = new NormalizeFloatListVector(); private final NormalizeFloatListVector nfv = new NormalizeFloatListVector();
@Override @Override
public CqlVector apply(CqlVector cqlVector) { public CqlVector apply(CqlVector<N> cqlVector) {
double[] vals = new double[cqlVector.size()]; double[] vals = new double[cqlVector.size()];
double accumulator= 0.0d; double accumulator = 0.0d;
for (int i = 0; i < vals.length; i++) { for (int i = 0; i < vals.length; i++) {
vals[i]=cqlVector.get(i).doubleValue(); vals[i] = cqlVector.get(i).doubleValue();
accumulator+=vals[i]*vals[i]; accumulator += vals[i] * vals[i];
} }
double factor = 1.0d/Math.sqrt(Arrays.stream(vals).map(d -> d * d).sum()); double factor = 1.0d / Math.sqrt(Arrays.stream(vals).map(d -> d * d).sum());
if (cqlVector.get(0) instanceof Float) { if (cqlVector.get(0) instanceof Float) {
List<Float> list = Arrays.stream(vals).mapToObj(d -> Float.valueOf((float) (d * factor))).toList(); List<Float> list =
Arrays.stream(vals).mapToObj(d -> Float.valueOf((float) (d * factor))).toList();
return CqlVector.newInstance(list); return CqlVector.newInstance(list);
} else if (cqlVector.get(0) instanceof Double) { } else if (cqlVector.get(0) instanceof Double) {
List<Double> list = Arrays.stream(vals).mapToObj(d -> Double.valueOf((float) (d * factor))).toList(); List<Double> list =
Arrays.stream(vals).mapToObj(d -> Double.valueOf((float) (d * factor))).toList();
return CqlVector.newInstance(list); return CqlVector.newInstance(list);
} else { } else {
throw new RuntimeException(NormalizeCqlVector.class.getCanonicalName()+ " only supports Double and Float type"); throw new RuntimeException(NormalizeCqlVector.class.getCanonicalName()
+ " only supports Double and Float type");
} }
} }
} }

View File

@ -46,9 +46,9 @@ public class NormalizeCqlVectorTest {
@Test @Test
public void normalizeCqlVectorDoubles() { public void normalizeCqlVectorDoubles() {
CqlVector square = CqlVector.newInstance(1.0d, 1.0d); CqlVector<Number> square = CqlVector.newInstance(1.0d, 1.0d);
NormalizeCqlVector nv = new NormalizeCqlVector(); NormalizeCqlVector nv = new NormalizeCqlVector();
CqlVector normaled = nv.apply(square); CqlVector<Number> normaled = nv.apply(square);
assertThat(normaled.size()).isEqualTo(2); assertThat(normaled.size()).isEqualTo(2);
assertThat(normaled.get(0)).isInstanceOf(Double.class); assertThat(normaled.get(0)).isInstanceOf(Double.class);

View File

@ -118,10 +118,10 @@ public class StandardActivity<R extends java.util.function.LongFunction, S> exte
} else { } else {
adapter = adapters.get(driverName); adapter = adapters.get(driverName);
} }
if (adapter instanceof NBConfigurable configurable) { // if (adapter instanceof NBConfigurable configurable) {
adapterModel = configurable.getConfigModel(); // adapterModel = configurable.getConfigModel();
adapterModel.assertValidConfig(ot.getParams()); // adapterModel.assertValidConfig(ot.getParams());
} // }
paramsAdvisor.validateAll(ot.getParams().keySet()); paramsAdvisor.validateAll(ot.getParams().keySet());
paramsAdvisor.validateAll(ot.getTags().keySet()); paramsAdvisor.validateAll(ot.getTags().keySet());
paramsAdvisor.validateAll(ot.getBindings().keySet()); paramsAdvisor.validateAll(ot.getBindings().keySet());

View File

@ -35,6 +35,7 @@ public class VirtDataFunctions {
LongUnaryOperator(java.util.function.LongUnaryOperator.class, long.class), LongUnaryOperator(java.util.function.LongUnaryOperator.class, long.class),
IntFunction(java.util.function.IntFunction.class, int.class), IntFunction(java.util.function.IntFunction.class, int.class),
IntUnaryOperator(java.util.function.IntUnaryOperator.class, int.class), IntUnaryOperator(java.util.function.IntUnaryOperator.class, int.class),
DoubleToLongFunction(java.util.function.DoubleToLongFunction.class, long.class),
DoubleToIntFunction(java.util.function.DoubleToIntFunction.class, int.class), DoubleToIntFunction(java.util.function.DoubleToIntFunction.class, int.class),
DoubleFunction(java.util.function.DoubleFunction.class, double.class), DoubleFunction(java.util.function.DoubleFunction.class, double.class),
DoubleUnaryOperator(java.util.function.DoubleUnaryOperator.class, double.class), DoubleUnaryOperator(java.util.function.DoubleUnaryOperator.class, double.class),
@ -60,46 +61,70 @@ public class VirtDataFunctions {
} }
/** /**
* Adapt a functional object into a different type of functional object. Adapt a functional object into a different type of functional object.
* @param func
* @param func The original function object. The original function object.
* @param type The type of function object needed. @param type
* @param output The output type required for the adapted function. The type of function object needed.
* @param truncate Whether to throw an exception on any narrowing conversion. If this is set to false, then basic @param output
* roll-over logic is applied on narrowing conversions. The output type required for the adapted function.
* @param <F> The type of function object needed. @param truncate
* @return An instance of F Whether to throw an exception on any narrowing conversion. If this is set to false, then
basic
roll-over logic is applied on narrowing conversions.
@param <F>
The type of function object needed.
@return An instance of F
*/ */
public static <F> F adapt(Object func, Class<F> type, Class<?> output, boolean truncate) { public static <F> F adapt(Object func, Class<F> type, Class<?> output, boolean truncate) {
FuncType funcType = FuncType.valueOf(type); FuncType funcType = FuncType.valueOf(type);
switch (funcType) { switch (funcType) {
case DoubleToLongFunction:
return truncate ? (F) adaptDoubleToLongFunction(func, output) :
(F) adaptDoubleToLongFunctionStrict(func, output);
case LongUnaryOperator: case LongUnaryOperator:
return truncate ? (F) adaptLongUnaryOperator(func, output) : (F) adaptLongUnaryOperatorStrict(func, output); return truncate ? (F) adaptLongUnaryOperator(func, output) :
(F) adaptLongUnaryOperatorStrict(func, output);
case DoubleUnaryOperator: case DoubleUnaryOperator:
return truncate ? (F) adaptDoubleUnaryOperator(func, output) : (F) adaptDoubleUnaryOperatorStrict(func, output); return truncate ? (F) adaptDoubleUnaryOperator(func, output) :
(F) adaptDoubleUnaryOperatorStrict(func, output);
case IntUnaryOperator: case IntUnaryOperator:
return truncate ? adaptIntUnaryOperator(func, output) : adaptIntUnaryOperatorStrict(func, output); return truncate ? adaptIntUnaryOperator(func, output) :
adaptIntUnaryOperatorStrict(func, output);
case DoubleFunction: case DoubleFunction:
return truncate ? adaptDoubleFunction(func, output) : adaptDoubleFunctionStrict(func, output); return truncate ? adaptDoubleFunction(func, output) :
adaptDoubleFunctionStrict(func, output);
case LongFunction: case LongFunction:
return truncate ? (F) adaptLongFunction(func, output) : (F) adaptLongFunctionStrict(func, output); return truncate ? (F) adaptLongFunction(func, output) :
(F) adaptLongFunctionStrict(func, output);
case LongToDoubleFunction: case LongToDoubleFunction:
return truncate ? (F) adaptLongToDoubleFunction(func, output) : (F) adaptLongToDoubleFunctionStrict(func, output); return truncate ? (F) adaptLongToDoubleFunction(func, output) :
(F) adaptLongToDoubleFunctionStrict(func, output);
case LongToIntFunction: case LongToIntFunction:
return truncate ? (F) adaptLongToIntFunction(func, output) : (F) adaptLongFunctionStrict(func, output); return truncate ? (F) adaptLongToIntFunction(func, output) :
(F) adaptLongFunctionStrict(func, output);
case IntFunction: case IntFunction:
return adaptIntFunction(func, output); return adaptIntFunction(func, output);
case Function: case Function:
return truncate ? (F) adaptFunction(func, output) : adaptFunctionStrict(func, output); return truncate ? (F) adaptFunction(func, output) :
adaptFunctionStrict(func, output);
default: default:
throw new RuntimeException("Unable to convert function type '" + funcType + "' (" + func.getClass().getName() + throw new RuntimeException(
") to " + type.getName() + (truncate ? " WITH " : " WITHOUT ") + "truncation"); "Unable to convert function type '" + funcType + "' (" + func.getClass()
.getName() + ") to " + type.getName() + (truncate ? " WITH " : " WITHOUT ")
+ "truncation");
} }
} }
public static <F extends Object> List<F> adaptList(Object[] funcs, Class<F> type, Class<?> output, boolean truncate) { public static <F extends Object> List<F> adaptList(
Object[] funcs,
Class<F> type,
Class<?> output,
boolean truncate
)
{
List<F> adapted = new ArrayList<>(); List<F> adapted = new ArrayList<>();
for (Object func : funcs) { for (Object func : funcs) {
F f = adapt(func, type, output, truncate); F f = adapt(func, type, output, truncate);
@ -109,7 +134,11 @@ public class VirtDataFunctions {
} }
private static LongToDoubleFunction adaptLongToDoubleFunctionStrict(Object func, Class<?> output) { private static LongToDoubleFunction adaptLongToDoubleFunctionStrict(
Object func,
Class<?> output
)
{
FuncType isaType = FuncType.valueOf(func.getClass()); FuncType isaType = FuncType.valueOf(func.getClass());
switch (isaType) { switch (isaType) {
case LongToDoubleFunction: case LongToDoubleFunction:
@ -119,62 +148,117 @@ public class VirtDataFunctions {
LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class);
return f2::applyAsInt; return f2::applyAsInt;
case LongFunction: case LongFunction:
LongFunction<Double> f3 = assertTypesAssignable(func, LongFunction.class, double.class); LongFunction<Double> f3 =
assertTypesAssignable(func, LongFunction.class, double.class);
return f3::apply; return f3::apply;
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class);
return f4::applyAsLong; return f4::applyAsLong;
case DoubleFunction: case DoubleFunction:
DoubleFunction<Double> f7 = assertTypesAssignable(func, DoubleFunction.class, double.class); DoubleFunction<Double> f7 =
assertTypesAssignable(func, DoubleFunction.class, double.class);
return f7::apply; return f7::apply;
case DoubleUnaryOperator: case DoubleUnaryOperator:
DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class); DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class);
return f8::applyAsDouble; return f8::applyAsDouble;
case Function: case Function:
Function<Double, Double> f9 = assertTypesAssignable(func, Function.class, double.class, double.class); Function<Double, Double> f9 =
assertTypesAssignable(func, Function.class, double.class, double.class);
return l -> f9.apply((double) l).doubleValue(); return l -> f9.apply((double) l).doubleValue();
case IntFunction: case IntFunction:
case IntUnaryOperator: case IntUnaryOperator:
throwNarrowingError(func, isaType.functionClazz); throwNarrowingError(func, isaType.functionClazz);
default: default:
throw new BasicError("I don't know how to convert a " + func.getClass().getName() + " function to a LongToDoubleFunction."); throw new BasicError("I don't know how to convert a " + func.getClass().getName()
+ " function to a LongToDoubleFunction.");
} }
} }
private static DoubleToLongFunction adaptDoubleToLongFunction(Object func, Class<?> output) {
FuncType isaType = FuncType.valueOf(func.getClass());
switch (isaType) {
case LongToDoubleFunction:
LongToDoubleFunction f1 = assertTypesAssignable(func, LongToDoubleFunction.class);
return l -> (long) f1.applyAsDouble((long) l);
case LongToIntFunction:
LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class);
return l -> f2.applyAsInt((long) l);
case LongFunction:
LongFunction<Long> f3 = assertTypesAssignable(func, LongFunction.class, Long.class);
return l -> f3.apply((long) l);
case LongUnaryOperator:
LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class);
return l -> f4.applyAsLong((long) l);
case IntFunction:
IntFunction<Long> f5 = assertTypesAssignable(func, IntFunction.class, Long.class);
return l -> f5.apply((int) l);
case IntUnaryOperator:
IntUnaryOperator f6 = assertTypesAssignable(func, IntUnaryOperator.class);
return l -> f6.applyAsInt((int) l);
case DoubleToLongFunction:
DoubleToLongFunction f7 = assertTypesAssignable(func, DoubleToLongFunction.class);
return l -> f7.applyAsLong((long) l);
case DoubleToIntFunction:
DoubleToIntFunction f8 = assertTypesAssignable(func, DoubleToIntFunction.class);
return l -> f8.applyAsInt((int) l);
case DoubleFunction:
DoubleFunction<Long> f9 =
assertTypesAssignable(func, DoubleFunction.class, Long.class);
return f9::apply;
case DoubleUnaryOperator:
DoubleUnaryOperator f10 = assertTypesAssignable(func, DoubleUnaryOperator.class);
return l -> (long) f10.applyAsDouble(l);
case Function:
Function<Double, Long> f11 =
assertTypesAssignable(func, Function.class, Double.class, Long.class);
return f11::apply;
default:
throw new BasicError("I don't know how to convert a " + func.getClass().getName()
+ " function to a DoubleToLongFunction.");
}
}
private static LongToDoubleFunction adaptLongToDoubleFunction(Object func, Class<?> output) { private static LongToDoubleFunction adaptLongToDoubleFunction(Object func, Class<?> output) {
FuncType isaType = FuncType.valueOf(func.getClass()); FuncType isaType = FuncType.valueOf(func.getClass());
switch (isaType) { switch (isaType) {
case LongToDoubleFunction: case LongToDoubleFunction:
LongToDoubleFunction f1 = assertTypesAssignable(func, LongToDoubleFunction.class); return assertTypesAssignable(func, LongToDoubleFunction.class);
return null;
case LongToIntFunction: case LongToIntFunction:
LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class);
return null; return f2::applyAsInt;
case LongFunction: case LongFunction:
LongFunction<Double> f3 = assertTypesAssignable(func, LongFunction.class, double.class); LongFunction<Double> f3 =
return null; assertTypesAssignable(func, LongFunction.class, double.class);
return f3::apply;
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class);
return null; return f4::applyAsLong;
case IntFunction: case IntFunction:
IntFunction<Double> f5 = assertTypesAssignable(func, IntFunction.class, double.class); IntFunction<Double> f5 =
return null; assertTypesAssignable(func, IntFunction.class, double.class);
return l -> f5.apply((int) l);
case IntUnaryOperator: case IntUnaryOperator:
IntUnaryOperator f6 = assertTypesAssignable(func, IntUnaryOperator.class); IntUnaryOperator f6 = assertTypesAssignable(func, IntUnaryOperator.class);
return null; return operand -> f6.applyAsInt((int) operand);
case DoubleFunction: case DoubleFunction:
DoubleFunction<Double> f7 = assertTypesAssignable(func, DoubleFunction.class, double.class); DoubleFunction<Double> f7 =
return null; assertTypesAssignable(func, DoubleFunction.class, double.class);
return f7::apply;
case DoubleUnaryOperator: case DoubleUnaryOperator:
DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class); DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class);
return null; return f8::applyAsDouble;
case Function: case Function:
Function<Double, Double> f9 = assertTypesAssignable(func, Function.class, double.class, double.class); Function<Double, Double> f9 =
return null; assertTypesAssignable(func, Function.class, double.class, double.class);
return t -> f9.apply((double) t);
default: default:
throw new BasicError("I don't know how to convert a " + func.getClass().getName() + " function to a LongToDoubleFunction."); throw new BasicError("I don't know how to convert a " + func.getClass().getName()
+ " function to a LongToDoubleFunction.");
} }
} }
@ -188,15 +272,32 @@ public class VirtDataFunctions {
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f2 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator f2 = assertTypesAssignable(func, LongUnaryOperator.class);
return f2::applyAsLong; return f2::applyAsLong;
case LongToDoubleFunction:
LongToDoubleFunction f7 = assertTypesAssignable(func, LongToDoubleFunction.class);
return f7::applyAsDouble;
case LongToIntFunction: case LongToIntFunction:
LongToIntFunction f3 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction f3 = assertTypesAssignable(func, LongToIntFunction.class);
return f3::applyAsInt; return f3::applyAsInt;
case DoubleToLongFunction:
DoubleToLongFunction f4 = assertTypesAssignable(func, DoubleToLongFunction.class);
return f4::applyAsLong;
case DoubleToIntFunction:
DoubleToIntFunction f5 = assertTypesAssignable(func, DoubleToIntFunction.class);
return f5::applyAsInt;
case DoubleFunction:
DoubleFunction<?> f6 = assertTypesAssignable(func, DoubleFunction.class);
return f6::apply;
case Function: case Function:
Function<Long, Long> f7 = assertTypesAssignable(func, Function.class, Long.class); Function<Long, Long> f8 = assertTypesAssignable(func, Function.class, Long.class);
return (long l) -> f7.apply(l); return f8::apply;
case DoubleUnaryOperator:
case IntUnaryOperator:
case IntFunction:
default: default:
throw new RuntimeException("Unable to convert " + func.getClass().getName() + " to a " + throw new RuntimeException(
LongUnaryOperator.class.getName() + " since this would cause a narrowing conversion."); "Unable to convert " + func.getClass().getName() + " to a "
+ LongUnaryOperator.class.getName()
+ " since this would cause a narrowing conversion.");
} }
} }
@ -206,48 +307,60 @@ public class VirtDataFunctions {
switch (isaType) { switch (isaType) {
case LongFunction: case LongFunction:
LongFunction<?> f1 = (LongFunction<?>) func; LongFunction<?> f1 = (LongFunction<?>) func;
Function<Long, ?> rf1 = f1::apply; return (Function<Long, ?>) f1::apply;
return rf1;
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f2 = (LongUnaryOperator) func; LongUnaryOperator f2 = (LongUnaryOperator) func;
Function<Long, Long> rf2 = f2::applyAsLong; return (Function<Long, Long>) f2::applyAsLong;
return rf2;
case IntFunction: case IntFunction:
IntFunction f3 = (IntFunction) func; IntFunction<?> f3 = (IntFunction<?>) func;
Function<Integer, ?> rf3 = f3::apply; return (Function<Integer, ?>) f3::apply;
return rf3;
case IntUnaryOperator: case IntUnaryOperator:
IntUnaryOperator f4 = (IntUnaryOperator) func; IntUnaryOperator f4 = (IntUnaryOperator) func;
Function<Integer, ?> rf4 = f4::applyAsInt; return (Function<Integer, ?>) f4::applyAsInt;
return rf4;
case DoubleFunction: case DoubleFunction:
DoubleFunction f5 = (DoubleFunction) func; DoubleFunction<?> f5 = (DoubleFunction<?>) func;
Function<Double, ?> rf5 = f5::apply; return (Function<Double, ?>) f5::apply;
return rf5;
case DoubleUnaryOperator: case DoubleUnaryOperator:
DoubleUnaryOperator f6 = (DoubleUnaryOperator) func; DoubleUnaryOperator f6 = (DoubleUnaryOperator) func;
Function<Double, ?> rf6 = f6::applyAsDouble; return (Function<Double, ?>) f6::applyAsDouble;
return rf6; case LongToDoubleFunction:
LongToDoubleFunction f10 = (LongToDoubleFunction) func;
return (Function<Long, Double>) f10;
case LongToIntFunction: case LongToIntFunction:
LongToIntFunction f7 = (LongToIntFunction) func; LongToIntFunction f7 = (LongToIntFunction) func;
Function<Long, Integer> rf7 = f7::applyAsInt; Function<Long, Integer> rf7 = f7::applyAsInt;
case Function: case Function:
return (Function<?, ?>) func; return (Function<?, ?>) func;
case DoubleToLongFunction:
DoubleToLongFunction f8 = (DoubleToLongFunction) func;
return (Function<Double, Long>) f8::applyAsLong;
case DoubleToIntFunction:
DoubleToIntFunction f9 = (DoubleToIntFunction) func;
return (Function<Double, Integer>) f9;
default: default:
throw new RuntimeException("Unable to map function:" + func); throw new RuntimeException("Unable to map function:" + func);
} }
} }
private static <F> F adaptFunctionStrict(Object func, Class<?> output) { private static <F> F adaptFunctionStrict(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptFunctionsStrict(Object,Class<?>)"); throw new RuntimeException(
"This must be implemented, now that it is used: adaptFunctionsStrict(Object,Class<?>)");
} }
private static <F> F adaptDoubleFunctionStrict(Object func, Class<?> output) { private static <F> F adaptDoubleFunctionStrict(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptDoubleFunctionStrict(Object,Class<?>) "); throw new RuntimeException(
"This must be implemented, now that it is used: adaptDoubleFunctionStrict(Object,Class<?>) ");
} }
private static LongFunction<?> adaptDoubleToLongFunctionStrict(Object func, Class<?> output) {
throw new RuntimeException(
"This must be implemented, now that it is used: adaptDoubleToLongFunctionStrict(Object,Class<?>)");
}
private static <F> F adaptIntUnaryOperatorStrict(Object func, Class<?> output) { private static <F> F adaptIntUnaryOperatorStrict(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptIntUnaryOperatorStrict(Object,Class<?>)"); throw new RuntimeException(
"This must be implemented, now that it is used: adaptIntUnaryOperatorStrict(Object,Class<?>)");
} }
private static DoubleUnaryOperator adaptDoubleUnaryOperator(Object func, Class<?> output) { private static DoubleUnaryOperator adaptDoubleUnaryOperator(Object func, Class<?> output) {
@ -255,7 +368,8 @@ public class VirtDataFunctions {
switch (toFuncType) { switch (toFuncType) {
case DoubleFunction: case DoubleFunction:
DoubleFunction<Double> f2 = assertTypesAssignable(func, DoubleFunction.class, double.class); DoubleFunction<Double> f2 =
assertTypesAssignable(func, DoubleFunction.class, double.class);
return f2::apply; return f2::apply;
case LongToDoubleFunction: case LongToDoubleFunction:
LongToDoubleFunction f3 = assertTypesAssignable(func, LongToDoubleFunction.class); LongToDoubleFunction f3 = assertTypesAssignable(func, LongToDoubleFunction.class);
@ -264,13 +378,15 @@ public class VirtDataFunctions {
LongToIntFunction f4 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction f4 = assertTypesAssignable(func, LongToIntFunction.class);
return l -> f4.applyAsInt((long) l % Long.MAX_VALUE); return l -> f4.applyAsInt((long) l % Long.MAX_VALUE);
case LongFunction: case LongFunction:
LongFunction<Double> f5 = assertTypesAssignable(func, LongFunction.class, double.class); LongFunction<Double> f5 =
assertTypesAssignable(func, LongFunction.class, double.class);
return l -> (double) f5.apply((long) l % Long.MAX_VALUE); return l -> (double) f5.apply((long) l % Long.MAX_VALUE);
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f6 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator f6 = assertTypesAssignable(func, LongUnaryOperator.class);
return l -> f6.applyAsLong((long) l % Long.MAX_VALUE); return l -> f6.applyAsLong((long) l % Long.MAX_VALUE);
case IntFunction: case IntFunction:
IntFunction<Double> f7 = assertTypesAssignable(func, IntFunction.class, double.class); IntFunction<Double> f7 =
assertTypesAssignable(func, IntFunction.class, double.class);
return l -> (double) f7.apply((int) l % Integer.MAX_VALUE); return l -> (double) f7.apply((int) l % Integer.MAX_VALUE);
case IntUnaryOperator: case IntUnaryOperator:
IntUnaryOperator f8 = assertTypesAssignable(func, IntUnaryOperator.class); IntUnaryOperator f8 = assertTypesAssignable(func, IntUnaryOperator.class);
@ -282,25 +398,31 @@ public class VirtDataFunctions {
DoubleUnaryOperator fA = assertTypesAssignable(func, DoubleUnaryOperator.class); DoubleUnaryOperator fA = assertTypesAssignable(func, DoubleUnaryOperator.class);
return fA; return fA;
case Function: case Function:
Function<Double, Double> f1 = assertTypesAssignable(func, Function.class, double.class, double.class); Function<Double, Double> f1 =
assertTypesAssignable(func, Function.class, double.class, double.class);
return f1::apply; return f1::apply;
default: default:
throw new IllegalStateException("Unexpected value: " + toFuncType); throw new IllegalStateException("Unexpected value: " + toFuncType);
} }
} }
private static DoubleUnaryOperator adaptDoubleUnaryOperatorStrict(Object func, Class<?> output) { private static DoubleUnaryOperator adaptDoubleUnaryOperatorStrict(Object func, Class<?> output)
{
FuncType toFuncType = FuncType.valueOf(func.getClass()); FuncType toFuncType = FuncType.valueOf(func.getClass());
switch (toFuncType) { switch (toFuncType) {
case Function: case Function:
Function<Double, Double> f1 = assertTypesAssignable(func, Function.class, double.class, double.class); Function<Double, Double> f1 =
assertTypesAssignable(func, Function.class, double.class, double.class);
return f1::apply; return f1::apply;
case DoubleFunction: case DoubleFunction:
DoubleFunction<Double> f2 = assertTypesAssignable(func, DoubleFunction.class, double.class); DoubleFunction<Double> f2 =
assertTypesAssignable(func, DoubleFunction.class, double.class);
return f2::apply; return f2::apply;
default: default:
throw new RuntimeException("Unable to convert " + func.getClass().getName() + " to a " + throw new RuntimeException(
DoubleUnaryOperator.class.getName() + " since this would cause a narrowing conversion."); "Unable to convert " + func.getClass().getName() + " to a "
+ DoubleUnaryOperator.class.getName()
+ " since this would cause a narrowing conversion.");
} }
} }
@ -315,16 +437,20 @@ public class VirtDataFunctions {
LongUnaryOperator o5 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator o5 = assertTypesAssignable(func, LongUnaryOperator.class);
return o5; return o5;
case Function: case Function:
Function<Long, Long> o7 = assertTypesAssignable(func, Function.class, long.class, long.class); Function<Long, Long> o7 =
assertTypesAssignable(func, Function.class, long.class, long.class);
return o7::apply; return o7::apply;
default: default:
throw new RuntimeException("Unable to convert " + func.getClass().getName() + " to a " + throw new RuntimeException(
LongUnaryOperator.class.getName() + " since this would cause a narrowing conversion."); "Unable to convert " + func.getClass().getName() + " to a "
+ LongUnaryOperator.class.getName()
+ " since this would cause a narrowing conversion.");
} }
} }
private static <F> F adaptIntFunction(Object func, Class<?> output) { private static <F> F adaptIntFunction(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptIntFunction(Object,Class<?>)"); throw new RuntimeException(
"This must be implemented, now that it is used: adaptIntFunction(Object,Class<?>)");
} }
protected static LongToIntFunction adaptLongToIntFunction(Object func, Class<?> output) { protected static LongToIntFunction adaptLongToIntFunction(Object func, Class<?> output) {
@ -332,31 +458,36 @@ public class VirtDataFunctions {
switch (isaType) { switch (isaType) {
case LongToDoubleFunction: case LongToDoubleFunction:
LongToDoubleFunction f1 = assertTypesAssignable(func, LongToDoubleFunction.class, double.class); LongToDoubleFunction f1 =
assertTypesAssignable(func, LongToDoubleFunction.class, double.class);
return l -> (int) (f1.applyAsDouble(l) % Integer.MAX_VALUE); return l -> (int) (f1.applyAsDouble(l) % Integer.MAX_VALUE);
case LongToIntFunction: case LongToIntFunction:
LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction f2 = assertTypesAssignable(func, LongToIntFunction.class);
return f2; return f2;
case LongFunction: case LongFunction:
LongFunction<Double> f3 = assertTypesAssignable(func, LongFunction.class, double.class); LongFunction<Double> f3 =
assertTypesAssignable(func, LongFunction.class, double.class);
return l -> (int) f3.apply((int) l % Integer.MAX_VALUE).longValue(); return l -> (int) f3.apply((int) l % Integer.MAX_VALUE).longValue();
case LongUnaryOperator: case LongUnaryOperator:
LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class); LongUnaryOperator f4 = assertTypesAssignable(func, LongUnaryOperator.class);
return l -> (int) (f4.applyAsLong(l) % Integer.MAX_VALUE); return l -> (int) (f4.applyAsLong(l) % Integer.MAX_VALUE);
case IntFunction: case IntFunction:
IntFunction<Long> f5 = assertTypesAssignable(func, IntFunction.class, double.class); IntFunction<Long> f5 = assertTypesAssignable(func, IntFunction.class, double.class);
return l -> (int) f5.apply((int) l % Integer.MAX_VALUE).longValue() % Integer.MAX_VALUE; return l -> (int) f5.apply((int) l % Integer.MAX_VALUE).longValue()
% Integer.MAX_VALUE;
case IntUnaryOperator: case IntUnaryOperator:
IntUnaryOperator f6 = assertTypesAssignable(func, IntUnaryOperator.class); IntUnaryOperator f6 = assertTypesAssignable(func, IntUnaryOperator.class);
return l -> f6.applyAsInt((int) l % Integer.MAX_VALUE); return l -> f6.applyAsInt((int) l % Integer.MAX_VALUE);
case DoubleFunction: case DoubleFunction:
DoubleFunction<Double> f7 = assertTypesAssignable(func, DoubleFunction.class, double.class); DoubleFunction<Double> f7 =
assertTypesAssignable(func, DoubleFunction.class, double.class);
return l -> (int) f7.apply(l).longValue() & Integer.MAX_VALUE; return l -> (int) f7.apply(l).longValue() & Integer.MAX_VALUE;
case DoubleUnaryOperator: case DoubleUnaryOperator:
DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class); DoubleUnaryOperator f8 = assertTypesAssignable(func, DoubleUnaryOperator.class);
return l -> (int) f8.applyAsDouble(l) % Integer.MAX_VALUE; return l -> (int) f8.applyAsDouble(l) % Integer.MAX_VALUE;
case Function: case Function:
Function<Double, Double> f9 = assertTypesAssignable(func, Function.class, double.class, double.class); Function<Double, Double> f9 =
assertTypesAssignable(func, Function.class, double.class, double.class);
return l -> (int) f9.apply((double) l).longValue() % Integer.MAX_VALUE; return l -> (int) f9.apply((double) l).longValue() % Integer.MAX_VALUE;
default: default:
throw new IllegalStateException("Unexpected value: " + isaType); throw new IllegalStateException("Unexpected value: " + isaType);
@ -397,29 +528,33 @@ public class VirtDataFunctions {
assertOutputAssignable(f9.applyAsInt(1L), output); assertOutputAssignable(f9.applyAsInt(1L), output);
return (long l) -> f9.applyAsInt(l); return (long l) -> f9.applyAsInt(l);
default: default:
throw new RuntimeException("Unable to convert " + func.getClass().getName() + " to a " + throw new RuntimeException(
LongUnaryOperator.class.getName()); "Unable to convert " + func.getClass().getName() + " to a "
+ LongUnaryOperator.class.getName());
} }
} }
private static void assertOutputAssignable(Object result, Class<?> clazz) { private static void assertOutputAssignable(Object result, Class<?> clazz) {
if (!ClassUtils.isAssignable(result.getClass(), clazz, true)) { if (!ClassUtils.isAssignable(result.getClass(), clazz, true)) {
throw new InvalidParameterException("Unable to assign type of " + result.getClass().getName() throw new InvalidParameterException(
+ " to " + clazz.getName()); "Unable to assign type of " + result.getClass().getName() + " to "
+ clazz.getName());
} }
// if (!clazz.isAssignableFrom(result.getClass())) { // if (!clazz.isAssignableFrom(result.getClass())) {
// throw new InvalidParameterException("Unable to assign type of " + result.getClass().getName() // throw new InvalidParameterException("Unable to assign type of " + result.getClass().getName()
// + " to " + clazz.getName()); // + " to " + clazz.getName());
// } // }
} }
private static <F> F adaptDoubleFunction(Object func, Class<?> output) { private static <F> F adaptDoubleFunction(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptDoubleFunction(Object,Class<?>)"); throw new RuntimeException(
"This must be implemented, now that it is used: adaptDoubleFunction(Object,Class<?>)");
} }
private static <F> F adaptIntUnaryOperator(Object func, Class<?> output) { private static <F> F adaptIntUnaryOperator(Object func, Class<?> output) {
throw new RuntimeException("This must be implemented, now that it is used: adaptIntUnaryOperator(Object,Class<?>)"); throw new RuntimeException(
"This must be implemented, now that it is used: adaptIntUnaryOperator(Object,Class<?>)");
} }
@ -434,7 +569,8 @@ public class VirtDataFunctions {
LongFunction<Long> o2 = assertTypesAssignable(func, LongFunction.class, long.class); LongFunction<Long> o2 = assertTypesAssignable(func, LongFunction.class, long.class);
return o2::apply; return o2::apply;
case DoubleFunction: case DoubleFunction:
DoubleFunction<Long> o3 = assertTypesAssignable(func, DoubleFunction.class, long.class); DoubleFunction<Long> o3 =
assertTypesAssignable(func, DoubleFunction.class, long.class);
return o3::apply; return o3::apply;
case IntUnaryOperator: case IntUnaryOperator:
IntUnaryOperator o4 = assertTypesAssignable(func, IntUnaryOperator.class); IntUnaryOperator o4 = assertTypesAssignable(func, IntUnaryOperator.class);
@ -446,7 +582,8 @@ public class VirtDataFunctions {
DoubleUnaryOperator o6 = assertTypesAssignable(func, DoubleUnaryOperator.class); DoubleUnaryOperator o6 = assertTypesAssignable(func, DoubleUnaryOperator.class);
return (long l) -> (long) (o6.applyAsDouble(l) % Long.MAX_VALUE); return (long l) -> (long) (o6.applyAsDouble(l) % Long.MAX_VALUE);
case Function: case Function:
Function<Long, Long> o7 = assertTypesAssignable(func, Function.class, long.class, long.class); Function<Long, Long> o7 =
assertTypesAssignable(func, Function.class, long.class, long.class);
return o7::apply; return o7::apply;
case LongToDoubleFunction: case LongToDoubleFunction:
LongToDoubleFunction o8 = assertTypesAssignable(func, LongToDoubleFunction.class); LongToDoubleFunction o8 = assertTypesAssignable(func, LongToDoubleFunction.class);
@ -455,49 +592,60 @@ public class VirtDataFunctions {
LongToIntFunction o9 = assertTypesAssignable(func, LongToIntFunction.class); LongToIntFunction o9 = assertTypesAssignable(func, LongToIntFunction.class);
return o9::applyAsInt; return o9::applyAsInt;
} }
throw new InvalidParameterException("Unable to convert " + func.getClass().getName() + " to a " + throw new InvalidParameterException(
LongUnaryOperator.class.getName()); "Unable to convert " + func.getClass().getName() + " to a "
+ LongUnaryOperator.class.getName());
} }
/** /**
* Given a base object and a wanted type to convert it to, assert that the type of the base object is assignable to Given a base object and a wanted type to convert it to, assert that the type of the base object
* the wanted type. Further, if the wanted type is a generic type, assert that additional classes are assignable to is assignable to
* the generic type parameters. Thus, if you want to assign to a generic type from a non-generic type, you must the wanted type. Further, if the wanted type is a generic type, assert that additional classes
* qualify the types of values that will be used in those generic parameter positions in declaration order. are assignable to
* the generic type parameters. Thus, if you want to assign to a generic type from a non-generic
* <p>This is useful for taking any object and a known type and reifying it as the known type so that it can be type, you must
* then used idiomatically with normal type awareness. This scenario occurs when you are accepting an open type for qualify the types of values that will be used in those generic parameter positions in
* flexibility but then need to narrow the type sufficiently for additional conversion in a type-safe way.</p> declaration order.
*
* @param base The object to be assigned to the wanted type <p>This is useful for taking any object and a known type and reifying it as the known type so
* @param wantType The class type that the base object needs to be assignable to that it can be
* @param clazzes The types of values which will checked against generic type parameters of the wanted type then used idiomatically with normal type awareness. This scenario occurs when you are accepting
* @param <T> Generic parameter T for the wanted type an open type for
* @return The original object casted to the wanted type after verification of parameter assignability flexibility but then need to narrow the type sufficiently for additional conversion in a
type-safe way.</p>
@param base
The object to be assigned to the wanted type
@param wantType
The class type that the base object needs to be assignable to
@param clazzes
The types of values which will checked against generic type parameters of the wanted type
@param <T>
Generic parameter T for the wanted type
@return The original object casted to the wanted type after verification of parameter assignability
*/ */
private static <T> T assertTypesAssignable( private static <T> T assertTypesAssignable(Object base, Class<T> wantType, Class<?>... clazzes)
Object base, {
Class<T> wantType,
Class<?>... clazzes) {
if (!wantType.isAssignableFrom(base.getClass())) { if (!wantType.isAssignableFrom(base.getClass())) {
throw new InvalidParameterException("Unable to assign " + wantType.getName() + " from " + throw new InvalidParameterException(
base.getClass().getName()); "Unable to assign " + wantType.getName() + " from " + base.getClass().getName());
} }
TypeVariable<? extends Class<?>>[] typeParameters = base.getClass().getTypeParameters(); TypeVariable<? extends Class<?>>[] typeParameters = base.getClass().getTypeParameters();
if (typeParameters.length > 0) { if (typeParameters.length > 0) {
if (clazzes.length != typeParameters.length) { if (clazzes.length != typeParameters.length) {
throw new InvalidParameterException( throw new InvalidParameterException(
"type parameter lengths are mismatched:" + clazzes.length + ", " + typeParameters.length "type parameter lengths are mismatched:" + clazzes.length + ", "
); + typeParameters.length);
} }
for (int i = 0; i < clazzes.length; i++) { for (int i = 0; i < clazzes.length; i++) {
Class<?> from = clazzes[i]; Class<?> from = clazzes[i];
TypeVariable<? extends Class<?>> to = typeParameters[i]; TypeVariable<? extends Class<?>> to = typeParameters[i];
boolean assignableFrom = to.getGenericDeclaration().isAssignableFrom(from); boolean assignableFrom = to.getGenericDeclaration().isAssignableFrom(from);
if (!assignableFrom) { if (!assignableFrom) {
throw new InvalidParameterException("Can not assign " + from.getName() + " to " + to.getGenericDeclaration().getName()); throw new InvalidParameterException(
"Can not assign " + from.getName() + " to " + to.getGenericDeclaration()
.getName());
} }
} }
@ -507,14 +655,16 @@ public class VirtDataFunctions {
} }
/** /**
* Throw an error indicating a narrowing conversion was attempted for strict conversion. Throw an error indicating a narrowing conversion was attempted for strict conversion.
* @param func
* @param func The source function to convert from The source function to convert from
* @param targetClass The target class which was requested @param targetClass
The target class which was requested
*/ */
private static void throwNarrowingError(Object func, Class<?> targetClass) { private static void throwNarrowingError(Object func, Class<?> targetClass) {
throw new BasicError("Converting from " + func.getClass().getName() + " to " + targetClass.getName() + throw new BasicError(
" is not allowed when strict conversion is requested."); "Converting from " + func.getClass().getName() + " to " + targetClass.getName()
+ " is not allowed when strict conversion is requested.");
} }

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.virtdata.library.basics.core.stathelpers;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.stream.Collectors;
/**
* Uses the alias sampling method to encode and sample from discrete probabilities,
* even over larger sets of data. This form requires a unit interval sample value
* between 0.0 and 1.0. Assuming the maximal amount of memory is used for distinct
* outcomes N, a memory buffer of N*16 bytes is required for this implementation,
* requiring 32MB of memory for 1M entries.
*
* This sampler should be shared between threads, and will be by default, in order
* to avoid many instances of a 32MB buffer on heap.
*/
public class AliasSamplerDoubleLong implements DoubleToLongFunction {
private final ByteBuffer stats; // tuples of double,int,int (unfair coin, direct pointers to referents)
private final double slotCount; // The number of fair die-roll slotCount that contain unfair coin probabilities
private static final int _r0=0;
private static final int _r1=_r0+Double.BYTES; // unfair coin
private static final int _r2=_r1+Long.BYTES; // + referent 1
public static int RECORD_LEN = _r2 + Long.BYTES; // + referent 2 = Record size for the above.
// for testing
AliasSamplerDoubleLong(ByteBuffer stats) {
this.stats = stats;
if ((stats.capacity()% RECORD_LEN)!=0) {
throw new RuntimeException("Misaligned ByteBuffer size, must be a multiple of " + RECORD_LEN);
}
slotCount = (stats.capacity()/ RECORD_LEN);
}
public AliasSamplerDoubleLong(List<EvProbLongDouble> events) {
int size = events.size();
int[] alias = new int[events.size()];
double[] prob = new double[events.size()];
LinkedList<EvProbLongDouble> small = new LinkedList<>();
LinkedList<EvProbLongDouble> large = new LinkedList<>();
List<Slot> slots = new ArrayList<>();
// array-size normalization
double sumProbability = events.stream().mapToDouble(EvProbLongDouble::prob).sum();
events = events.stream().map(e -> new EvProbLongDouble(e.id(),
(e.prob()/sumProbability)*size)).collect(Collectors.toList());
// presort
for (EvProbLongDouble event : events) {
(event.prob()<1.0D ? small : large).addLast(event);
}
while (small.peekFirst()!=null && large.peekFirst()!=null) {
EvProbLongDouble l = small.removeFirst();
EvProbLongDouble g = large.removeFirst();
slots.add(new Slot(g.id(), l.id(), l.prob()));
EvProbLongDouble remainder = new EvProbLongDouble(g.id(),(g.prob()+l.prob())-1);
(remainder.prob()<1.0D ? small : large).addLast(remainder);
}
while (large.peekFirst()!=null) {
EvProbLongDouble g = large.removeFirst();
slots.add(new Slot(g.id(),g.id(),1.0));
}
while (small.peekFirst()!=null) {
EvProbLongDouble l = small.removeFirst();
slots.add(new Slot(l.id(),l.id(),1.0));
}
if (slots.size()!=size) {
throw new RuntimeException("basis for average probability is incorrect, because only " + slots.size() + " slotCount of " + size + " were created.");
}
// align to indexes
for (int i = 0; i < slots.size(); i++) {
slots.set(i,slots.get(i).rescale(i, i+1));
}
this.stats = ByteBuffer.allocate(slots.size()* RECORD_LEN);
for (Slot slot : slots) {
stats.putDouble(slot.botProb);
stats.putLong(slot.botId());
stats.putLong(slot.topId());
}
stats.flip();
this.slotCount = (stats.capacity()/ RECORD_LEN);
}
@Override
public long applyAsLong(double value) {
double fractionlPoint = value * slotCount;
int offsetPoint = (int) fractionlPoint * RECORD_LEN;
double divider = stats.getDouble(offsetPoint);
int selector = offsetPoint+ (fractionlPoint>divider?_r2:_r1);
long referentId = stats.getLong(selector);
return referentId;
}
private record Slot(long topId, long botId, double botProb){
public Slot rescale(int min, int max) {
return new Slot(topId, botId, (min + (botProb*(max-min))));
}
};
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.virtdata.library.basics.core.stathelpers;
import java.util.Comparator;
public record EvProbLongDouble(long id, double prob) {
}

View File

@ -0,0 +1,78 @@
package io.nosqlbench.virtdata.library.basics.shared.from_double.to_long;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.nosqlbench.virtdata.api.annotations.Categories;
import io.nosqlbench.virtdata.api.annotations.Category;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.api.bindings.VirtDataFunctions;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.AliasSamplerDoubleLong;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.EvProbLongDouble;
import io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.EmpiricalDistribution;
import io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.HashRange;
import java.util.ArrayList;
import java.util.List;
import java.util.function.DoubleToLongFunction;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongUnaryOperator;
@ThreadSafeMapper
@Categories(Category.distributions)
public class IntervalHistribution implements LongUnaryOperator {
private final UnitHistribution sampler;
private final LongToDoubleFunction samplePointF;
@Example({"IntervalHistribution('50 25 13 12')", "implied frequencies of 0:50 1:25 2:13 3:12"})
@Example({
"IntervalHistribution('234:50 33:25 17:13 3:12')",
"labeled frequencies; 234,33,17,3 are labels, and 50,25,13,12 are weights"
})
public IntervalHistribution(String freqs, Object samplePointFunc) {
this.sampler = new UnitHistribution(freqs);
this.samplePointF = VirtDataFunctions.adapt(
samplePointFunc,
LongToDoubleFunction.class,
double.class,
false
);
}
public IntervalHistribution(String freqs) {
this(freqs,new HashRange(0.0d,1.0d));
}
private static List<EvProbLongDouble> genEvents(long[] freqs) {
ArrayList<EvProbLongDouble> events = new ArrayList<>();
for (int i = 0; i < freqs.length; i++) {
events.add(new EvProbLongDouble(i, freqs[i]));
}
return events;
}
@Override
public long applyAsLong(long operand) {
double samplePoint = this.samplePointF.applyAsDouble(operand);
return this.sampler.applyAsLong(samplePoint);
}
}

View File

@ -0,0 +1,78 @@
package io.nosqlbench.virtdata.library.basics.shared.from_double.to_long;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.nosqlbench.virtdata.api.annotations.Categories;
import io.nosqlbench.virtdata.api.annotations.Category;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.AliasSamplerDoubleLong;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.EvProbLongDouble;
import io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.EmpiricalDistribution;
import java.util.ArrayList;
import java.util.List;
import java.util.function.DoubleToLongFunction;
/// Empirical Histribution is a portmanteau name to capture the
/// concept of an empirical distribution based on a discrete histogram.
/// This is in contrast to the other similar method [EmpiricalDistribution],
/// which uses a continuous density estimation. Both excel in specific ways.
///
/// Use this distribution when you have a set of label frequencies which you
/// want to represent accurately.
@ThreadSafeMapper
@Categories(Category.distributions)
public class UnitHistribution extends AliasSamplerDoubleLong implements DoubleToLongFunction {
@Example({"UnitHistribution('50 25 13 12')", "implied frequencies of 0:50 1:25 2:13 3:12"})
@Example({
"UnitHistribution('234:50 33:25 17:13 3:12')",
"labeled frequencies; 234,33,17,3 are labels, and 50,25,13,12 are weights"
})
public UnitHistribution(String freqs) {
List<EvProbLongDouble> events = new ArrayList<>();
boolean labeled = (freqs.contains(":"));
String[] elems = freqs.split("[,; ]");
for (int i = 0; i < elems.length; i++) {
String[] parts = elems[i].split(":", 2);
if ((parts.length == 1 && labeled) || (parts.length == 2 && !labeled)) {
throw new RuntimeException(
"If any elements are labeled, all elements must be:" + freqs);
}
long id = labeled ? Long.parseLong(parts[0]) : i;
long weight = Long.parseLong(parts[labeled ? 1 : 0]);
events.add(new EvProbLongDouble(id, weight));
}
super(events);
}
// public UnitHistribution(long... freqs) {
// super(genEvents(freqs));
// }
//
// private static List<EvProbLongDouble> genEvents(long[] freqs) {
// ArrayList<EvProbLongDouble> events = new ArrayList<>();
// for (int i = 0; i < freqs.length; i++) {
// events.add(new EvProbLongDouble(i, freqs[i]));
// }
// return events;
// }
}

View File

@ -0,0 +1,147 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_double;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.nosqlbench.virtdata.api.annotations.Categories;
import io.nosqlbench.virtdata.api.annotations.Category;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.api.bindings.VirtDataConversions;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongUnaryOperator;
/// Blends two functions with a domain of 0..Long.MAX_VALUE as the input interval,
/// and a double output. The output value is interpolated between the output value
/// of the two according to the mix function. When the mix function yields a value
/// of 0.0, then the mix is turned _fully counter-clockwise_., or fully on the first provided
/// function. When the value is 1.0, the mix is turned all the clockwise, or fully on the second
/// provided function.
///
/// If there are only two inner functions provided to HashMix, then it will default to
/// sampling random mixes at a randomized sample point. In other words, the variates
/// provided will be somewhere between the two curves on the unit interval. This is a simple way
/// to sample between two curves by default. The yielded value will be greater than or equal to
/// the lower of the two values at any point, and less than or equal to the greater of either.
///
/// If a third parameter is provided to control the mix, then the mix can be set directly as a
/// unit interval. (The dial goes from 0.0 to 1.0). Any double or float value here will suffice.
/// You can use this when you want to have a test parameter that slews between two modeled
/// shapes. You can alternately provide any other function which can be coerced to a LongToDouble
/// function as a dynamic mix control. IFF such a function is provided, it must also be responsible
/// for hashing the input value if pseudo-randomness is desired.
///
/// If a fourth parameter is provided, the sample point can also be controlled. By default, the
/// values on the provided curves will be sampled pseudo-randomly. However, a fourth parameter
/// can override this just like the mix ratio. As well, if you provide a value or function
/// to control the sample point, you are also responsible for any hashing needed to sample across
/// the whole space of possible values.
///
/// The flexibility of these two parameters provides a substantial amount of flexibility. You
/// can, for example:
///
/// - sample variates between two curves
/// - sample variates at a selected morphing step between the curves
/// - sample variates between two curves on a subsection of the unit interval
/// - sample variates within a defined band gap of the two curves
@ThreadSafeMapper
@Categories(Category.functional)
public class HashMix implements LongToDoubleFunction {
private final LongToDoubleFunction f1;
private final LongToDoubleFunction f2;
private final LongToDoubleFunction mixF;
private final LongUnaryOperator sampleF;
@Example({
"HashMix(Func1(),Func2())",
"yield samples between func1 and func2 values at some random random sample point x"
})
@Example({
"HashMix(Func1(),Func2(),0.25d)",
"yield samples which are 25% from the sample values for func1 and func2 at some random "
+ "sample point x"
})
@Example({
"HashMix(Func1(),Func2(),HashRange(0.25d,0.75d)",
"yield samples between 25% and 75% from func1 to func2 values at some random sample point x"
})
@Example({
"HashMix(Func1(),Func2(),0.0d,ScaledDouble())",
"access Func1 values as if it were the only one provided. ScaledDouble adds no "
+ "randomization the input value, but it does map it to the sample domain of 0.0d-0.1d."
})
public HashMix(Object curve1F, Object curve2F, Object mixPointF, Object samplePointF) {
if (mixPointF instanceof Double v) {
if (v > 1.0d || v < 0.0d) {
throw new RuntimeException(
"mix value (" + v + ") must be within the unit" + " range [0.0d,1.0d]");
}
this.mixF = n -> v;
} else if (mixPointF instanceof Float v) {
if (v > 1.0d || v < 0.0d) {
throw new RuntimeException(
"mix value (" + v + ") must be within the unit" + " range [0.0d,1.0d]");
}
this.mixF = n -> v;
} else {
this.mixF = VirtDataConversions.adaptFunction(mixPointF, LongToDoubleFunction.class);
}
this.f1 = VirtDataConversions.adaptFunction(curve1F, LongToDoubleFunction.class);
this.f2 = VirtDataConversions.adaptFunction(curve2F, LongToDoubleFunction.class);
this.sampleF = VirtDataConversions.adaptFunction(samplePointF, LongUnaryOperator.class);
}
public HashMix(Object curve1F, Object curve2F, Object mixPointF) {
this(
curve1F,
curve2F,
mixPointF,
new io.nosqlbench.virtdata.library.basics.shared.from_long.to_long.HashRange(Long.MAX_VALUE)
);
}
public HashMix(Object curve1F, Object curve2F) {
this(
curve1F,
curve2F,
new HashRange(0.0d, 1.0d),
new io.nosqlbench.virtdata.library.basics.shared.from_long.to_long.HashRange(Long.MAX_VALUE)
);
}
public HashMix(LongToDoubleFunction f1, LongToDoubleFunction f2) {
this(
f1,
f2,
new HashRange(0.0d, 1.0d),
new io.nosqlbench.virtdata.library.basics.shared.from_long.to_long.HashRange(Long.MAX_VALUE)
);
}
@Override
public double applyAsDouble(long value) {
long sampleAt = sampleF.applyAsLong(value);
double v1 = f1.applyAsDouble(sampleAt);
double v2 = f2.applyAsDouble(sampleAt);
double mix = mixF.applyAsDouble(value);
return LERP.lerp(v1, v2, mix);
}
}

View File

@ -0,0 +1,25 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_double;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
public class LERP {
public static double lerp(double v1, double v2, double mix) {
return v1 + (v2 - v1) * mix;
}
}

View File

@ -0,0 +1,122 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_long;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.nosqlbench.virtdata.api.annotations.Categories;
import io.nosqlbench.virtdata.api.annotations.Category;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongUnaryOperator;
/// Blends two functions with a domain of 0..Long.MAX_VALUE as the input interval,
/// and a double output. The output value is interpolated between the output value
/// of the two according to the mix function. When the mix function yields a value
/// of 0.0, then the mix is turned _fully counter-clockwise_., or fully on the first provided
/// function. When the value is 1.0, the mix is turned all the clockwise, or fully on the second
/// provided function.
///
/// If there are only two inner functions provided to HashMix, then it will default to
/// sampling random mixes at a randomized sample point. In other words, the variates
/// provided will be somewhere between the two curves on the unit interval. This is a simple way
/// to sample between two curves by default. The yielded value will be greater than or equal to
/// the lower of the two values at any point, and less than or equal to the greater of either.
///
/// If a third parameter is provided to control the mix, then the mix can be set directly as a
/// unit interval. (The dial goes from 0.0 to 1.0). Any double or float value here will suffice.
/// You can use this when you want to have a test parameter that slews between two modeled
/// shapes. You can alternately provide any other function which can be coerced to a LongToDouble
/// function as a dynamic mix control. IFF such a function is provided, it must also be responsible
/// for hashing the input value if pseudo-randomness is desired.
///
/// If a fourth parameter is provided, the sample point can also be controlled. By default, the
/// values on the provided curves will be sampled pseudo-randomly. However, a fourth parameter
/// can override this just like the mix ratio. As well, if you provide a value or function
/// to control the sample point, you are also responsible for any hashing needed to sample across
/// the whole space of possible values.
///
/// The flexibility of these two parameters provides a substantial amount of flexibility. You
/// can, for example:
///
/// - sample variates between two curves
/// - sample variates at a selected morphing step between the curves
/// - sample variates between two curves on a subsection of the unit interval
/// - sample variates within a defined band gap of the two curves
@ThreadSafeMapper
@Categories(Category.functional)
public class HashMix implements LongUnaryOperator {
private io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.HashMix mixer;
@Example({
"IntervalHashMix(Func1(),Func2())",
"yield samples between func1 and func2 values at some random random sample point x"
})
@Example({
"IntervalHashMix(Func1(),Func2(),0.25d)",
"yield samples which are 25% from the sample values for func1 and func2 at some random "
+ "sample point x"
})
@Example({
"IntervalHashMix(Func1(),Func2(),HashRange(0.25d,0.75d)",
"yield samples between 25% and 75% from func1 to func2 values at some random sample point x"
})
@Example({
"IntervalHashMix(Func1(),Func2(),0.0d,ScaledDouble())",
"access Func1 values as if it were the only one provided. ScaledDouble adds no "
+ "randomization the input value, but it does map it to the sample domain of 0.0d-0.1d."
})
public HashMix(Object curve1F, Object curve2F, Object mixPointF, Object samplePointF) {
this.mixer = new io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.HashMix(curve1F, curve2F, mixPointF, samplePointF);
}
public HashMix(Object curve1F, Object curve2F, Object mixPointF) {
this(
curve1F,
curve2F,
mixPointF,
new HashRange(Long.MAX_VALUE)
);
}
public HashMix(Object curve1F, Object curve2F) {
this(
curve1F,
curve2F,
new io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.HashRange(0.0d, 1.0d),
new HashRange(Long.MAX_VALUE)
);
}
public HashMix(LongToDoubleFunction f1, LongToDoubleFunction f2) {
this(
f1,
f2,
new io.nosqlbench.virtdata.library.basics.shared.from_long.to_double.HashRange(0.0d, 1.0d),
new HashRange(Long.MAX_VALUE)
);
}
@Override
public long applyAsLong(long value) {
return (long) mixer.applyAsDouble(value);
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.virtdata.library.basics.core.stathelpers.aliasmethod;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.AliasSamplerDoubleInt;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.AliasSamplerDoubleLong;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.EvProbD;
import io.nosqlbench.virtdata.library.basics.core.stathelpers.EvProbLongDouble;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class AliasSamplerDoubleLongTest {
private final static Logger logger = LogManager.getLogger(AliasSamplerDoubleLongTest.class);
@Test
public void testAliasSamplerBinaryFractions() {
List<EvProbLongDouble> events = new ArrayList();
events.add(new EvProbLongDouble(1L,1.0D));
events.add(new EvProbLongDouble(2L,1.0D));
events.add(new EvProbLongDouble(3L,2.0D));
events.add(new EvProbLongDouble(4L,4.0D));
events.add(new EvProbLongDouble(5L,8.0D));
events.add(new EvProbLongDouble(6L,16.0D));
events.add(new EvProbLongDouble(7L,32.0D));
events.add(new EvProbLongDouble(8L,64.0D));
AliasSamplerDoubleLong as = new AliasSamplerDoubleLong(events);
int[] stats = new int[9];
for (int i = 0; i < 10000; i++) {
double v = (double)i / 10000D;
long idx = as.applyAsLong(v);
stats[(int)idx]++;
}
logger.debug(Arrays.toString(stats));
assertThat(stats).containsExactly(0,79,79,157,313,626,1250,2499,4997);
}
@Test
public void testAliasSamplerSimple() {
List<EvProbD> events = new ArrayList<>();
events.add(new EvProbD(1,1D));
events.add(new EvProbD(2,2D));
events.add(new EvProbD(3,3D));
AliasSamplerDoubleInt as = new AliasSamplerDoubleInt(events);
int[] stats = new int[4];
for (int i = 0; i < 10000; i++) {
double v = (double)i / 10000D;
int idx = as.applyAsInt(v);
stats[idx]++;
}
logger.debug(Arrays.toString(stats));
assertThat(stats).containsExactly(0,1667,3334,4999);
}
}

View File

@ -0,0 +1,87 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_double;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.assertj.core.data.Offset;
import org.junit.jupiter.api.Test;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongUnaryOperator;
import static org.assertj.core.api.Assertions.assertThat;
public class HashMixTest {
private final static LongToDoubleFunction TO_UNIT_INTERVAL =
(l) -> ((double) l) / ((double) Long.MAX_VALUE);
private final static Object TO_UNIT_INTERVAL_OBJ = (Object) TO_UNIT_INTERVAL;
@Test
public void testLinearMix() {
DoubleHolder dh = new DoubleHolder();
LongHolder lh = new LongHolder();
HashMix um1 = new HashMix(TO_UNIT_INTERVAL, TO_UNIT_INTERVAL,dh, lh);
for (long i = 0; i >= 0L; i += 1L << 58) {
double fraction = TO_UNIT_INTERVAL.applyAsDouble(i);
lh.setValue(i);
dh.setValue(fraction);
double actual = um1.applyAsDouble(i);
double expected = TO_UNIT_INTERVAL.applyAsDouble(i);
assertThat(actual).isEqualTo(expected, Offset.offset(0.0000001d));
}
}
@Test
public void testCrossfadeMix() {
LongToDoubleFunction rampdown1 = l -> 1.0d - TO_UNIT_INTERVAL.applyAsDouble(l);
LongToDoubleFunction rampdown2 = l -> 2.0d - TO_UNIT_INTERVAL.applyAsDouble(l);
HashMix um1 = new HashMix(rampdown1, rampdown2);
for (long i = 0; i >= 0L; i += 1L << 58) {
double value = um1.applyAsDouble(i);
assertThat(um1.applyAsDouble(i)).isEqualTo(1.0d, Offset.offset(0.0000001d));
}
}
private class DoubleHolder implements LongToDoubleFunction {
private double value;
@Override
public double applyAsDouble(long value) {
return this.value;
}
public void setValue(double value) {
this.value = value;
}
}
private class LongHolder implements LongUnaryOperator {
private long value;
@Override
public long applyAsLong(long operand) {
return this.value;
}
public void setValue(long value) {
this.value = value;
}
}
}

View File

@ -0,0 +1,37 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_double;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.assertj.core.data.Offset;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
public class LERPTest {
@Test
public void testDoubleLerp() {
assertThat(LERP.lerp(10.0d,10.0d,1.0d)).isEqualTo(10.0d, Offset.offset(0.00001d));
assertThat(LERP.lerp(10.0d,0.0d,0.0d)).isEqualTo(10.0d, Offset.offset(0.00001d));
assertThat(LERP.lerp(10.0d,0.0d,1.0d)).isEqualTo(0.0d, Offset.offset(0.00001d));
assertThat(LERP.lerp(10.0d,5.0d,0.5d)).isEqualTo(7.5d, Offset.offset(0.00001d));
}
}

View File

@ -0,0 +1,57 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_double;
/*
* Copyright (c) nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.nosqlbench.virtdata.library.basics.shared.from_double.to_long.UnitHistribution;
import org.assertj.core.data.Offset;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class UnitHistributionTest {
@Test
public void testUniformSyntaxRequired() {
assertThatThrownBy(() -> new UnitHistribution("1 2:2 3:3")).hasMessageContaining(
"all elements must be");
}
@Test
public void testBasicHistribution() {
UnitHistribution h = new UnitHistribution("1:1 2:2 3:3");
long[] counts = new long[10];
int total=1000000;
HashRange hr = new HashRange(0.0d, 1.0d);
for (int i = 0; i < total; i++) {
double hash = hr.applyAsDouble(i);
long v = h.applyAsLong(hash);
counts[(int)v]++;
}
assertThat((double) counts[0] / (double) total).isEqualTo(0.0d, Offset.offset(0.01));
assertThat((double) counts[1] / (double) total).isEqualTo(0.16666666d, Offset.offset(0.01));
assertThat((double) counts[2] / (double) total).isEqualTo(0.33333333d,
Offset.offset(0.01));
assertThat((double) counts[3] / (double) total).isEqualTo(0.5d, Offset.offset(0.01));
System.out.println(Arrays.toString(counts));
}
}