mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 16:12:01 +00:00
add sign math function
This commit is contained in:
parent
ccb7e6e03f
commit
667119918e
@ -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
98
src/Functions/sign.cpp
Normal 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>();
|
||||
}
|
||||
}
|
@ -428,6 +428,7 @@ SRCS(
|
||||
runningDifference.cpp
|
||||
runningDifferenceStartingWithFirstValue.cpp
|
||||
sigmoid.cpp
|
||||
sign.cpp
|
||||
sin.cpp
|
||||
sinh.cpp
|
||||
sleep.cpp
|
||||
|
23
tests/queries/0_stateless/01670_sign_function.reference
Normal file
23
tests/queries/0_stateless/01670_sign_function.reference
Normal 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
|
32
tests/queries/0_stateless/01670_sign_function.sql
Normal file
32
tests/queries/0_stateless/01670_sign_function.sql
Normal 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;
|
Loading…
Reference in New Issue
Block a user