Skip to content

Commit

Permalink
Specify the floating point accuracy of the round() function (#3178)
Browse files Browse the repository at this point in the history
* round modification

* add test and fix problem

* fix

* add test

* switch to if

* add test

Co-authored-by: Yee <[email protected]>
  • Loading branch information
jackwener and yixinglu authored Nov 3, 2021
1 parent cb0e528 commit 07ccfde
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/common/function/FunctionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ std::unordered_map<std::string, std::vector<TypeSignature>> FunctionManager::typ
TypeSignature({Value::Type::FLOAT}, Value::Type::FLOAT)}},
{"round",
{TypeSignature({Value::Type::INT}, Value::Type::FLOAT),
TypeSignature({Value::Type::FLOAT}, Value::Type::FLOAT)}},
TypeSignature({Value::Type::INT, Value::Type::INT}, Value::Type::FLOAT),
TypeSignature({Value::Type::FLOAT}, Value::Type::FLOAT),
TypeSignature({Value::Type::FLOAT, Value::Type::INT}, Value::Type::FLOAT)}},
{"sqrt",
{TypeSignature({Value::Type::INT}, Value::Type::FLOAT),
TypeSignature({Value::Type::FLOAT}, Value::Type::FLOAT)}},
Expand Down Expand Up @@ -539,17 +541,23 @@ FunctionManager::FunctionManager() {
// to nearest integral (as a floating-point value)
auto &attr = functions_["round"];
attr.minArity_ = 1;
attr.maxArity_ = 1;
attr.maxArity_ = 2;
attr.isPure_ = true;
attr.body_ = [](const auto &args) -> Value {
switch (args[0].get().type()) {
case Value::Type::NULLVALUE: {
return Value::kNullValue;
}
case Value::Type::INT: {
return std::round(args[0].get().getInt());
}
case Value::Type::INT:
case Value::Type::FLOAT: {
if (args.size() == 2) {
if (args[1].get().type() == Value::Type::INT) {
auto decimal = args[1].get().getInt();
return std::round(args[0].get().getFloat() * pow(10, decimal)) / pow(10, decimal);
} else {
return Value::kNullBadType;
}
}
return std::round(args[0].get().getFloat());
}
default: {
Expand Down
18 changes: 18 additions & 0 deletions src/common/function/test/FunctionManagerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ std::unordered_map<std::string, std::vector<Value>> FunctionManagerTest::args_ =
{"one", {-1.2}},
{"two", {2, 4}},
{"pow", {2, 3}},
{"round1", {11111.11111, 2}},
{"round2", {11111.11111, -1}},
{"round3", {11111.11111, -5}},
{"radians", {180}},
{"range1", {1, 5}},
{"range2", {1, 5, 2}},
Expand Down Expand Up @@ -268,6 +271,11 @@ TEST_F(FunctionManagerTest, functionCall) {
TEST_FUNCTION(log, args_["int"], std::log(4));
TEST_FUNCTION(log2, args_["int"], 2.0);
}
{
TEST_FUNCTION(round, args_["round1"], 11111.11);
TEST_FUNCTION(round, args_["round2"], 11110.0);
TEST_FUNCTION(round, args_["round3"], 0.0);
}
{
TEST_FUNCTION(range, args_["range1"], Value(List({1, 2, 3, 4, 5})));
TEST_FUNCTION(range, args_["range2"], Value(List({1, 3, 5})));
Expand Down Expand Up @@ -916,11 +924,21 @@ TEST_F(FunctionManagerTest, returnType) {
ASSERT_TRUE(result.ok());
EXPECT_EQ(result.value(), Value::Type::FLOAT);
}
{
auto result = FunctionManager::getReturnType("round", {Value::Type::INT, Value::Type::INT});
ASSERT_TRUE(result.ok());
EXPECT_EQ(result.value(), Value::Type::FLOAT);
}
{
auto result = FunctionManager::getReturnType("round", {Value::Type::FLOAT});
ASSERT_TRUE(result.ok());
EXPECT_EQ(result.value(), Value::Type::FLOAT);
}
{
auto result = FunctionManager::getReturnType("round", {Value::Type::FLOAT, Value::Type::INT});
ASSERT_TRUE(result.ok());
EXPECT_EQ(result.value(), Value::Type::FLOAT);
}
{
auto result = FunctionManager::getReturnType("cbrt", {Value::Type::INT});
ASSERT_TRUE(result.ok());
Expand Down
44 changes: 44 additions & 0 deletions tests/tck/features/expression/FunctionCall.feature
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,50 @@ Feature: Function Call Expression
| result |
| NULL |

Scenario: round
When executing query:
"""
YIELD round(3.1415926, 9) as result
"""
Then the result should be, in any order:
| result |
| 3.1415926 |
When executing query:
"""
YIELD round(3.1415926, 2) as result
"""
Then the result should be, in any order:
| result |
| 3.14 |
When executing query:
"""
YIELD round(3.1415926, 3) as result
"""
Then the result should be, in any order:
| result |
| 3.142 |
When executing query:
"""
YIELD round(3.14159265359, 0) as result
"""
Then the result should be, in any order:
| result |
| 3.0 |
When executing query:
"""
YIELD round(35543.14159265359, -3) as result
"""
Then the result should be, in any order:
| result |
| 36000.0 |
When executing query:
"""
YIELD round(35543.14159265359, -5) as result
"""
Then the result should be, in any order:
| result |
| 0.0 |

Scenario: error check
When executing query:
"""
Expand Down

0 comments on commit 07ccfde

Please sign in to comment.