Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,17 @@ decay_result:double
1.0
;

unsignedLongLinear
required_capability: decay_function

ROW value = 15::unsigned_long
| EVAL decay_result = decay(value, 10::unsigned_long, 10::unsigned_long, {"offset": 10000000000, "decay": 0.5, "type": "linear"})
| KEEP decay_result;

decay_result:double
1.0
;

cartesianPointLinear1
required_capability: decay_function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import static org.elasticsearch.xpack.esql.core.type.DataType.LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT;
import static org.elasticsearch.xpack.esql.core.type.DataType.TIME_DURATION;
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
import static org.elasticsearch.xpack.esql.core.type.DataType.isDateNanos;
import static org.elasticsearch.xpack.esql.core.type.DataType.isGeoPoint;
import static org.elasticsearch.xpack.esql.core.type.DataType.isMillisOrNanos;
Expand Down Expand Up @@ -91,7 +92,7 @@ public class Decay extends EsqlScalarFunction implements OptionalArgument, PostO

private static final Map<String, Collection<DataType>> ALLOWED_OPTIONS = Map.of(
OFFSET,
Set.of(TIME_DURATION, INTEGER, LONG, DOUBLE, KEYWORD, TEXT),
Set.of(TIME_DURATION, INTEGER, LONG, UNSIGNED_LONG, DOUBLE, KEYWORD, TEXT),
DECAY,
Set.of(DOUBLE),
TYPE,
Expand Down Expand Up @@ -140,25 +141,25 @@ public Decay(
Source source,
@Param(
name = "value",
type = { "double", "integer", "long", "date", "date_nanos", "geo_point", "cartesian_point" },
type = { "double", "integer", "long", "unsigned_long", "date", "date_nanos", "geo_point", "cartesian_point" },
description = "The input value to apply decay scoring to."
) Expression value,
@Param(
name = ORIGIN,
type = { "double", "integer", "long", "date", "date_nanos", "geo_point", "cartesian_point" },
type = { "double", "integer", "long", "unsigned_long", "date", "date_nanos", "geo_point", "cartesian_point" },
description = "Central point from which the distances are calculated."
) Expression origin,
@Param(
name = SCALE,
type = { "double", "integer", "long", "time_duration", "keyword", "text" },
type = { "double", "integer", "long", "unsigned_long", "time_duration", "keyword", "text" },
description = "Distance from the origin where the function returns the decay value."
) Expression scale,
@MapParam(
name = "options",
params = {
@MapParam.MapParamEntry(
name = OFFSET,
type = { "double", "integer", "long", "time_duration", "keyword", "text" },
type = { "double", "integer", "long", "unsigned_long", "time_duration", "keyword", "text" },
description = "Distance from the origin where no decay occurs."
),
@MapParam.MapParamEntry(
Expand Down Expand Up @@ -310,7 +311,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua
decayFolded,
decayFunction
);
case LONG -> new DecayLongEvaluator.Factory(
case LONG, UNSIGNED_LONG -> new DecayLongEvaluator.Factory(
source(),
valueFactory,
(Long) originFolded,
Expand Down Expand Up @@ -634,7 +635,7 @@ private Long getTemporalOffsetAsNanos(FoldContext foldCtx, Expression offset) {
private Object getDefaultOffset(DataType valueDataType) {
return switch (valueDataType) {
case INTEGER -> DEFAULT_INTEGER_OFFSET;
case LONG -> DEFAULT_LONG_OFFSET;
case LONG, UNSIGNED_LONG -> DEFAULT_LONG_OFFSET;
case DOUBLE -> DEFAULT_DOUBLE_OFFSET;
case GEO_POINT -> DEFAULT_GEO_POINT_OFFSET;
case CARTESIAN_POINT -> DEFAULT_CARTESIAN_POINT_OFFSET;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,33 @@ public static Iterable<Object[]> parameters() {
// Long random
testCaseSuppliers.addAll(longRandomTestCases());

// Unsigned Long Linear
testCaseSuppliers.addAll(unsignedLongTestCase(0L, 10L, 10000000L, 200L, 0.33, "linear", 1.0));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check how unsigned long test cases are generated for some ideas on how to generate numbers that don't fit into long

testCaseSuppliers.addAll(unsignedLongTestCase(10L, 10L, 10000000L, 200L, 0.33, "linear", 1.0));
testCaseSuppliers.addAll(unsignedLongTestCase(50000L, 10L, 10000000L, 200L, 0.33, "linear", 0.99666407));
testCaseSuppliers.addAll(unsignedLongTestCase(300000L, 10L, 10000000L, 200L, 0.33, "linear", 0.97991407));
testCaseSuppliers.addAll(unsignedLongTestCase(123456789112123L, 10L, 10000000L, 200L, 0.33, "linear", 0.0));

// Unsigned Long Exponential
testCaseSuppliers.addAll(unsignedLongTestCase(0L, 10L, 10000000L, 200L, 0.33, "exp", 1.0));
testCaseSuppliers.addAll(unsignedLongTestCase(10L, 10L, 10000000L, 200L, 0.33, "exp", 1.0));
testCaseSuppliers.addAll(unsignedLongTestCase(50000L, 10L, 10000000L, 200L, 0.33, "exp", 0.9944951761701727));
testCaseSuppliers.addAll(unsignedLongTestCase(300000L, 10L, 10000000L, 200L, 0.33, "exp", 0.9673096701204178));
testCaseSuppliers.addAll(unsignedLongTestCase(123456789112123L, 10L, 10000000L, 200L, 0.33, "exp", 0.0));

// Unsigned Long Gaussian
testCaseSuppliers.addAll(unsignedLongTestCase(0L, 10L, 10000000L, 200L, 0.33, "gauss", 1.0));
testCaseSuppliers.addAll(unsignedLongTestCase(10L, 10L, 10000000L, 200L, 0.33, "gauss", 1.0));
testCaseSuppliers.addAll(unsignedLongTestCase(50000L, 10L, 10000000L, 200L, 0.33, "gauss", 0.999972516142306));
testCaseSuppliers.addAll(unsignedLongTestCase(300000L, 10L, 10000000L, 200L, 0.33, "gauss", 0.9990040963055015));
testCaseSuppliers.addAll(unsignedLongTestCase(123456789112123L, 10L, 10000000L, 200L, 0.33, "gauss", 0.0));

// Unsigned Long defaults
testCaseSuppliers.addAll(unsignedLongTestCase(10L, 0L, 10L, null, null, null, 0.5));

// Unsigned Long random
testCaseSuppliers.addAll(unsignedLongRandomTestCases());

// Double Linear
testCaseSuppliers.addAll(doubleTestCase(0.0, 10.0, 10000000.0, 200.0, 0.25, "linear", 1.0));
testCaseSuppliers.addAll(doubleTestCase(10.0, 10.0, 10000000.0, 200.0, 0.25, "linear", 1.0));
Expand Down Expand Up @@ -738,6 +765,69 @@ private static List<TestCaseSupplier> longRandomTestCases() {
}));
}

private static List<TestCaseSupplier> unsignedLongTestCase(
long value,
long origin,
long scale,
Long offset,
Double decay,
String functionType,
double expected
) {
return List.of(
new TestCaseSupplier(
List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG, DataType.SOURCE),
() -> new TestCaseSupplier.TestCase(
List.of(
new TestCaseSupplier.TypedData(value, DataType.UNSIGNED_LONG, "value"),
new TestCaseSupplier.TypedData(origin, DataType.UNSIGNED_LONG, "origin").forceLiteral(),
new TestCaseSupplier.TypedData(scale, DataType.UNSIGNED_LONG, "scale").forceLiteral(),
new TestCaseSupplier.TypedData(createOptionsMap(offset, decay, functionType), DataType.SOURCE, "options")
.forceLiteral()
),
startsWith("DecayLongEvaluator["),
DataType.DOUBLE,
closeTo(expected, Math.ulp(expected))
)
)
);
}

private static List<TestCaseSupplier> unsignedLongRandomTestCases() {
return List.of(
new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG, DataType.SOURCE), () -> {
long randomValue = randomLong();
long randomOrigin = randomLong();
long randomScale = randomLong();
long randomOffset = randomLong();
double randomDecay = randomDouble();
String randomType = randomFrom("linear", "gauss", "exp");

double scoreScriptNumericResult = longDecayWithScoreScript(
randomValue,
randomOrigin,
randomScale,
randomOffset,
randomDecay,
randomType
);

return new TestCaseSupplier.TestCase(
List.of(
new TestCaseSupplier.TypedData(randomValue, DataType.UNSIGNED_LONG, "value"),
new TestCaseSupplier.TypedData(randomOrigin, DataType.UNSIGNED_LONG, "origin").forceLiteral(),
new TestCaseSupplier.TypedData(randomScale, DataType.UNSIGNED_LONG, "scale").forceLiteral(),
new TestCaseSupplier.TypedData(createOptionsMap(randomOffset, randomDecay, randomType), DataType.SOURCE, "options")
.forceLiteral()
),
startsWith("DecayLongEvaluator["),
DataType.DOUBLE,
equalTo(scoreScriptNumericResult)
);
})
);
}

private static double longDecayWithScoreScript(long value, long origin, long scale, long offset, double decay, String type) {
return switch (type) {
case "linear" -> new ScoreScriptUtils.DecayNumericLinear(origin, scale, offset, decay).decayNumericLinear(value);
Expand Down