Skip to content

Commit

Permalink
Updated EXPM1() and Tests to New Engine (#215) (opensearch-project#1334)
Browse files Browse the repository at this point in the history
* Updated EXPM1() and tests to new engine

Signed-off-by: Matthew Wells <matthew.wells@improving.com>
  • Loading branch information
matthewryanwells committed Feb 14, 2023
1 parent 4df8ed7 commit e990201
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 68 deletions.
4 changes: 4 additions & 0 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ public static FunctionExpression exp(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.EXP, expressions);
}

public static FunctionExpression expm1(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.EXPM1, expressions);
}

public static FunctionExpression floor(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.FLOOR, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public enum BuiltinFunctionName {
CRC32(FunctionName.of("crc32")),
E(FunctionName.of("e")),
EXP(FunctionName.of("exp")),
EXPM1(FunctionName.of("expm1")),
FLOOR(FunctionName.of("floor")),
LN(FunctionName.of("ln")),
LOG(FunctionName.of("log")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.opensearch.sql.data.model.ExprNullValue;
import org.opensearch.sql.data.model.ExprShortValue;
import org.opensearch.sql.data.model.ExprStringValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.data.type.ExprType;
import org.opensearch.sql.expression.function.BuiltinFunctionName;
Expand Down Expand Up @@ -59,6 +60,7 @@ public static void register(BuiltinFunctionRepository repository) {
repository.register(crc32());
repository.register(euler());
repository.register(exp());
repository.register(expm1());
repository.register(floor());
repository.register(ln());
repository.register(log());
Expand All @@ -85,6 +87,23 @@ public static void register(BuiltinFunctionRepository repository) {
repository.register(tan());
}

/**
* Base function for math functions with similar formats that return DOUBLE.
*
* @param functionName BuiltinFunctionName of math function.
* @param formula lambda function of math formula.
* @param returnType data type return type of the calling function
* @return DefaultFunctionResolver for math functions.
*/
private static DefaultFunctionResolver baseMathFunction(
FunctionName functionName, SerializableFunction<ExprValue,
ExprValue> formula, ExprCoreType returnType) {
return FunctionDSL.define(functionName,
ExprCoreType.numberTypes().stream().map(type -> FunctionDSL.impl(
FunctionDSL.nullMissingHandling(formula),
returnType, type)).collect(Collectors.toList()));
}

/**
* Definition of abs() function. The supported signature of abs() function are INT -> INT LONG ->
* LONG FLOAT -> FLOAT DOUBLE -> DOUBLE
Expand Down Expand Up @@ -186,15 +205,21 @@ private static DefaultFunctionResolver euler() {
}

/**
* Definition of exp(x) function. Calculate exponent function e to the x The supported signature
* of exp function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
* Definition of exp(x) function. Calculate exponent function e to the x
* The supported signature of exp function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver exp() {
return FunctionDSL.define(BuiltinFunctionName.EXP.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.exp(v.doubleValue()))),
type, DOUBLE)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.EXP.getName(),
v -> new ExprDoubleValue(Math.exp(v.doubleValue())), DOUBLE);
}

/**
* Definition of expm1(x) function. Calculate exponent function e to the x, minus 1
* The supported signature of exp function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver expm1() {
return baseMathFunction(BuiltinFunctionName.EXPM1.getName(),
v -> new ExprDoubleValue(Math.expm1(v.doubleValue())), DOUBLE);
}

/**
Expand All @@ -214,11 +239,8 @@ private static DefaultFunctionResolver floor() {
* ln function is INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver ln() {
return FunctionDSL.define(BuiltinFunctionName.LN.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.log(v.doubleValue()))),
type, DOUBLE)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.LN.getName(),
v -> new ExprDoubleValue(Math.log(v.doubleValue())), DOUBLE);
}

/**
Expand Down Expand Up @@ -255,23 +277,17 @@ private static DefaultFunctionResolver log() {
* log function is SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver log10() {
return FunctionDSL.define(BuiltinFunctionName.LOG10.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.log10(v.doubleValue()))),
type, DOUBLE)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.LOG10.getName(),
v -> new ExprDoubleValue(Math.log10(v.doubleValue())), DOUBLE);
}

/**
* Definition of log2(x) function. Calculate base-2 logarithm of x The supported signature of log
* function is SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver log2() {
return FunctionDSL.define(BuiltinFunctionName.LOG2.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2))), DOUBLE, type))
.collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.LOG2.getName(),
v -> new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2)), DOUBLE);
}

/**
Expand Down Expand Up @@ -450,11 +466,8 @@ private static DefaultFunctionResolver round() {
* SHORT/INTEGER/LONG/FLOAT/DOUBLE -> INTEGER
*/
private static DefaultFunctionResolver sign() {
return FunctionDSL.define(BuiltinFunctionName.SIGN.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprIntegerValue(Math.signum(v.doubleValue()))),
INTEGER, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.SIGN.getName(),
v -> new ExprIntegerValue(Math.signum(v.doubleValue())), INTEGER);
}

/**
Expand All @@ -464,12 +477,9 @@ private static DefaultFunctionResolver sign() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver sqrt() {
return FunctionDSL.define(BuiltinFunctionName.SQRT.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> v.doubleValue() < 0 ? ExprNullValue.of() :
new ExprDoubleValue(Math.sqrt(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.SQRT.getName(),
v -> v.doubleValue() < 0 ? ExprNullValue.of() :
new ExprDoubleValue(Math.sqrt(v.doubleValue())), DOUBLE);
}

/**
Expand All @@ -479,11 +489,8 @@ private static DefaultFunctionResolver sqrt() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver cbrt() {
return FunctionDSL.define(BuiltinFunctionName.CBRT.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.cbrt(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.CBRT.getName(),
v -> new ExprDoubleValue(Math.cbrt(v.doubleValue())), DOUBLE);
}

/**
Expand Down Expand Up @@ -606,11 +613,8 @@ private static DefaultFunctionResolver atan2() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver cos() {
return FunctionDSL.define(BuiltinFunctionName.COS.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.cos(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.COS.getName(),
v -> new ExprDoubleValue(Math.cos(v.doubleValue())), DOUBLE);
}

/**
Expand Down Expand Up @@ -641,11 +645,8 @@ private static DefaultFunctionResolver cot() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver degrees() {
return FunctionDSL.define(BuiltinFunctionName.DEGREES.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.toDegrees(v.doubleValue()))),
type, DOUBLE)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.DEGREES.getName(),
v -> new ExprDoubleValue(Math.toDegrees(v.doubleValue())), DOUBLE);
}

/**
Expand All @@ -655,11 +656,8 @@ private static DefaultFunctionResolver degrees() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver radians() {
return FunctionDSL.define(BuiltinFunctionName.RADIANS.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.toRadians(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.RADIANS.getName(),
v -> new ExprDoubleValue(Math.toRadians(v.doubleValue())), DOUBLE);
}

/**
Expand All @@ -669,11 +667,8 @@ private static DefaultFunctionResolver radians() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver sin() {
return FunctionDSL.define(BuiltinFunctionName.SIN.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.sin(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.SIN.getName(),
v -> new ExprDoubleValue(Math.sin(v.doubleValue())), DOUBLE);
}

/**
Expand All @@ -683,10 +678,7 @@ private static DefaultFunctionResolver sin() {
* INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
*/
private static DefaultFunctionResolver tan() {
return FunctionDSL.define(BuiltinFunctionName.TAN.getName(),
ExprCoreType.numberTypes().stream()
.map(type -> FunctionDSL.impl(FunctionDSL.nullMissingHandling(
v -> new ExprDoubleValue(Math.tan(v.doubleValue()))),
DOUBLE, type)).collect(Collectors.toList()));
return baseMathFunction(BuiltinFunctionName.TAN.getName(),
v -> new ExprDoubleValue(Math.tan(v.doubleValue())), DOUBLE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,90 @@ public void exp_missing_value() {
assertTrue(exp.valueOf(valueEnv()).isMissing());
}

/**
* Test expm1 with integer value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(ints = {
-1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE})
public void expm1_int_value(Integer value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test expm1 with long value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(longs = {
-1L, 0L, 1L, Long.MAX_VALUE, Long.MIN_VALUE})
public void expm1_long_value(Long value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test expm1 with float value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(floats = {
-1.5F, -1F, 0F, 1F, 1.5F, Float.MAX_VALUE, Float.MIN_VALUE})
public void expm1_float_value(Float value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test expm1 with double value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(doubles = {
-1.5D, -1D, 0D, 1D, 1.5D, Double.MAX_VALUE, Double.MIN_VALUE})
public void expm1_double_value(Double value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test expm1 with short value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(shorts = {
-1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE})
public void expm1_short_value(Short value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test expm1 with short value.
*/
@ParameterizedTest(name = "expm1({0})")
@ValueSource(bytes = {
-1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE})
public void expm1_byte_value(Byte value) {
FunctionExpression expm1 = DSL.expm1(DSL.literal(value));
assertThat(
expm1.valueOf(valueEnv()),
allOf(hasType(DOUBLE), hasValue(Math.expm1(value))));
assertEquals(String.format("expm1(%s)", value), expm1.toString());
}

/**
* Test floor with integer value.
*/
Expand All @@ -575,7 +659,7 @@ public void floor_int_value(Integer value) {
assertThat(
floor.valueOf(valueEnv()),
allOf(hasType(LONG), hasValue((long) Math.floor(value))));
assertEquals(String.format("floor(%s)", value.toString()), floor.toString());
assertEquals(String.format("floor(%s)", value), floor.toString());
}

/**
Expand Down
15 changes: 13 additions & 2 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,21 @@ EXPM1
Description
>>>>>>>>>>>

Specifications:
Usage: EXPM1(NUMBER T) returns the exponential of T, minus 1.

Argument type: INTEGER/LONG/FLOAT/DOUBLE

1. EXPM1(NUMBER T) -> T
Return type: DOUBLE

Example::

os> SELECT EXPM1(-1), EXPM1(0), EXPM1(1), EXPM1(1.5)
fetched rows / total rows = 1/1
+---------------------+------------+-------------------+-------------------+
| EXPM1(-1) | EXPM1(0) | EXPM1(1) | EXPM1(1.5) |
|---------------------+------------+-------------------+-------------------|
| -0.6321205588285577 | 0.0 | 1.718281828459045 | 3.481689070338065 |
+---------------------+------------+-------------------+-------------------+

FLOOR
-----
Expand Down
4 changes: 3 additions & 1 deletion docs/user/ppl/functions/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Example::
| c | 44 | 1100 | 15 |
+----------------------+----------------------+-------------------+---------------------+


COS
---

Expand Down Expand Up @@ -278,6 +279,7 @@ Example::
| 89.95437383553924 |
+-------------------+


E
-

Expand Down Expand Up @@ -309,7 +311,7 @@ Usage: exp(x) return e raised to the power of x.

Argument type: INTEGER/LONG/FLOAT/DOUBLE

Return type: INTEGER
Return type: DOUBLE

Example::

Expand Down
Loading

0 comments on commit e990201

Please sign in to comment.