add sign math function

This commit is contained in:
feng lv 2021-01-24 05:18:59 +00:00
parent ccb7e6e03f
commit 667119918e
5 changed files with 156 additions and 0 deletions

View File

@ -33,6 +33,7 @@ void registerFunctionAsinh(FunctionFactory & factory);
void registerFunctionAcosh(FunctionFactory & factory);
void registerFunctionAtanh(FunctionFactory & factory);
void registerFunctionPow(FunctionFactory & factory);
void registerFunctionSign(FunctionFactory & factory);
void registerFunctionsMath(FunctionFactory & factory)
@ -68,6 +69,7 @@ void registerFunctionsMath(FunctionFactory & factory)
registerFunctionAcosh(factory);
registerFunctionAtanh(factory);
registerFunctionPow(factory);
registerFunctionSign(factory);
}
}

98
src/Functions/sign.cpp Normal file
View File

@ -0,0 +1,98 @@
#include <Columns/ColumnVector.h>
#include <DataTypes/DataTypesNumber.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/IFunction.h>
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
class FunctionSign : public IFunction
{
private:
const Context & context;
public:
static constexpr auto name = "sign";
explicit FunctionSign(const Context & context_) : context(context_) { }
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionSign>(context); }
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 1; }
bool useDefaultImplementationForConstants() const override { return true; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
if (!isNumber(arguments[0].type))
throw Exception(
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Argument of function {} should be a number, got {}",
getName(),
arguments[0].type->getName());
ColumnWithTypeAndName compare_elem{arguments[0].column, arguments[0].type, {}};
auto greater = FunctionFactory::instance().get("greater", context);
auto greater_compare = greater->build(ColumnsWithTypeAndName{compare_elem, compare_elem});
if (isUnsignedInteger(arguments[0].type.get()))
{
return greater_compare->getResultType();
}
auto compare_type = greater_compare->getResultType();
ColumnWithTypeAndName minus_elem = {compare_type, {}};
auto minus = FunctionFactory::instance().get("minus", context);
auto elem_minus = minus->build(ColumnsWithTypeAndName{minus_elem, minus_elem});
return elem_minus->getResultType();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
auto zero_column = arguments[0].type->createColumnConstWithDefaultValue(input_rows_count);
ColumnWithTypeAndName left{arguments[0].column, arguments[0].type, {}};
ColumnWithTypeAndName right{zero_column, arguments[0].type, {}};
auto greater = FunctionFactory::instance().get("greater", context);
auto greater_compare = greater->build(ColumnsWithTypeAndName{left, right});
/// Unsigned number: sign(n) = greater(n, 0)
if (isUnsignedInteger(arguments[0].type.get()))
{
return greater_compare->execute({left, right}, greater_compare->getResultType(), input_rows_count);
}
/// Signed number: sign(n) = minus (greater(n, 0), less(n, 0))
auto less = FunctionFactory::instance().get("less", context);
auto less_compare = less->build(ColumnsWithTypeAndName{left, right});
ColumnsWithTypeAndName columns(2);
columns[0].type = greater_compare->getResultType();
columns[0].column = greater_compare->execute({left, right}, greater_compare->getResultType(), input_rows_count);
columns[1].type = less_compare->getResultType();
columns[1].column = less_compare->execute({left, right}, less_compare->getResultType(), input_rows_count);
auto minus = FunctionFactory::instance().get("minus", context);
auto elem_minus = minus->build(columns);
return elem_minus->execute(columns, elem_minus->getResultType(), input_rows_count);
}
};
void registerFunctionSign(FunctionFactory & factory)
{
factory.registerFunction<FunctionSign>();
}
}

View File

@ -428,6 +428,7 @@ SRCS(
runningDifference.cpp
runningDifferenceStartingWithFirstValue.cpp
sigmoid.cpp
sign.cpp
sin.cpp
sinh.cpp
sleep.cpp

View File

@ -0,0 +1,23 @@
0
1
-1
sign(Int32)
1
-1
1
sign(UInt32)
1
0
1
sign(Float32)
-1
1
1
sign(Float64)
1
-1
0
sign(Decimal32(5))
1
-1
1

View File

@ -0,0 +1,32 @@
SELECT sign(0);
SELECT sign(1);
SELECT sign(-1);
DROP TABLE IF EXISTS test;
CREATE TABLE test(
n1 Int32,
n2 UInt32,
n3 Float32,
n4 Float64,
n5 Decimal32(5)
) ENGINE = Memory;
INSERT INTO test VALUES (1, 2, -0.0001, 1.5, 0.5) (-2, 0, 2.5, -4, -5) (4, 5, 5, 0, 7);
SELECT 'sign(Int32)';
SELECT sign(n1) FROM test;
SELECT 'sign(UInt32)';
SELECT sign(n2) FROM test;
SELECT 'sign(Float32)';
SELECT sign(n3) FROM test;
SELECT 'sign(Float64)';
SELECT sign(n4) FROM test;
SELECT 'sign(Decimal32(5))';
SELECT sign(n5) FROM test;
DROP TABLE test;