Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated EXPM1() and Tests to New Engine #215

Merged
merged 20 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e2a6901
Updated EXPM1() and tests to new engine
matthewryanwells Feb 2, 2023
e357cdd
Added EXPM1 to PPL Parser
matthewryanwells Feb 2, 2023
c152a95
Added documentation for EXPM1 PPL and fixed small mistake in EXP docu…
matthewryanwells Feb 2, 2023
b5ab93e
Added newline to fix code style issue
matthewryanwells Feb 2, 2023
2958c3e
removed unnecessary integration tests and fixed typo in another test
matthewryanwells Feb 2, 2023
3c856a3
Extracted common code from math functions into external function
matthewryanwells Feb 6, 2023
b1c9fde
Added javadoc comment to new function
matthewryanwells Feb 6, 2023
457a5a6
Improved Javadoc
matthewryanwells Feb 6, 2023
f013e7d
Pulling changes from upstream
matthewryanwells Feb 7, 2023
6d09e77
Added and improved EXPM1 tests, and improved documentation for CLI an…
matthewryanwells Feb 7, 2023
eecd489
Removed EXPM1 from PPL
matthewryanwells Feb 8, 2023
8b88d1c
Updated math base function to take any type and included more functio…
matthewryanwells Feb 8, 2023
7a028d4
Made tiny change to documentation
matthewryanwells Feb 8, 2023
4574275
reverted euler function to previous iteration as the one I made didn'…
matthewryanwells Feb 8, 2023
62cc771
fixed typo in a comment that I made in a previous commit
matthewryanwells Feb 9, 2023
689a1dc
fixed a mistake I made in fixing the typo from my last commit
matthewryanwells Feb 9, 2023
5a3b724
Fixed spacing inconsistencies in math.rst file
matthewryanwells Feb 9, 2023
8042ebe
removed the base math function so that it can be pushed in a seperate…
matthewryanwells Feb 10, 2023
a74ae35
Reverted reverted change that removes the refactoring as this will be…
matthewryanwells Feb 10, 2023
e5a7001
updated base function to have more descriptive variables
matthewryanwells Feb 10, 2023
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
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 dataType data type input for the function
matthewryanwells marked this conversation as resolved.
Show resolved Hide resolved
* @return DefaultFunctionResolver for math functions.
*/
private static DefaultFunctionResolver baseMathFunction(
FunctionName functionName, SerializableFunction<ExprValue,
ExprValue> formula, ExprCoreType dataType) {
return FunctionDSL.define(functionName,
ExprCoreType.numberTypes().stream().map(type -> FunctionDSL.impl(
FunctionDSL.nullMissingHandling(formula),
dataType, 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 @@ -181,20 +200,26 @@ private static DefaultFunctionResolver crc32() {
*/
private static DefaultFunctionResolver euler() {
return FunctionDSL.define(BuiltinFunctionName.E.getName(),
FunctionDSL.impl(() -> new ExprDoubleValue(Math.E), DOUBLE)
FunctionDSL.impl(() -> new ExprDoubleValue(Math.E), DOUBLE)
matthewryanwells marked this conversation as resolved.
Show resolved Hide resolved
);
}

/**
* 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})")
matthewryanwells marked this conversation as resolved.
Show resolved Hide resolved
@ValueSource(ints = {
-1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE})
matthewryanwells marked this conversation as resolved.
Show resolved Hide resolved
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