mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
dbms: add intDivOrZero function. [#METR-13159]
This commit is contained in:
parent
eaa8a75a63
commit
813742e5d7
@ -139,6 +139,22 @@ inline void throwIfDivisionLeadsToFPE(A a, B b)
|
|||||||
throw Exception("Division of minimal signed number by minus one", ErrorCodes::ILLEGAL_DIVISION);
|
throw Exception("Division of minimal signed number by minus one", ErrorCodes::ILLEGAL_DIVISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
inline bool divisionLeadsToFPE(A a, B b)
|
||||||
|
{
|
||||||
|
/// Возможно, лучше вместо проверок использовать siglongjmp?
|
||||||
|
|
||||||
|
if (unlikely(b == 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/// http://avva.livejournal.com/2548306.html
|
||||||
|
if (unlikely(std::is_signed<A>::value && std::is_signed<B>::value && a == std::numeric_limits<A>::min() && b == -1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
|
||||||
@ -155,6 +171,18 @@ struct DivideIntegralImpl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename A, typename B>
|
||||||
|
struct DivideIntegralOrZeroImpl
|
||||||
|
{
|
||||||
|
typedef typename NumberTraits::ResultOfIntegerDivision<A, B>::Type ResultType;
|
||||||
|
|
||||||
|
template <typename Result = ResultType>
|
||||||
|
static inline Result apply(A a, B b)
|
||||||
|
{
|
||||||
|
return unlikely(divisionLeadsToFPE(a, b)) ? 0 : static_cast<Result>(a) / b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename A, typename B>
|
template<typename A, typename B>
|
||||||
struct ModuloImpl
|
struct ModuloImpl
|
||||||
{
|
{
|
||||||
@ -752,6 +780,7 @@ struct NameMinus { static constexpr auto name = "minus"; };
|
|||||||
struct NameMultiply { static constexpr auto name = "multiply"; };
|
struct NameMultiply { static constexpr auto name = "multiply"; };
|
||||||
struct NameDivideFloating { static constexpr auto name = "divide"; };
|
struct NameDivideFloating { static constexpr auto name = "divide"; };
|
||||||
struct NameDivideIntegral { static constexpr auto name = "intDiv"; };
|
struct NameDivideIntegral { static constexpr auto name = "intDiv"; };
|
||||||
|
struct NameDivideIntegralOrZero { static constexpr auto name = "intDivOrZero"; };
|
||||||
struct NameModulo { static constexpr auto name = "modulo"; };
|
struct NameModulo { static constexpr auto name = "modulo"; };
|
||||||
struct NameNegate { static constexpr auto name = "negate"; };
|
struct NameNegate { static constexpr auto name = "negate"; };
|
||||||
struct NameBitAnd { static constexpr auto name = "bitAnd"; };
|
struct NameBitAnd { static constexpr auto name = "bitAnd"; };
|
||||||
@ -766,6 +795,7 @@ typedef FunctionBinaryArithmetic<MinusImpl, NameMinus> FunctionMinus;
|
|||||||
typedef FunctionBinaryArithmetic<MultiplyImpl, NameMultiply> FunctionMultiply;
|
typedef FunctionBinaryArithmetic<MultiplyImpl, NameMultiply> FunctionMultiply;
|
||||||
typedef FunctionBinaryArithmetic<DivideFloatingImpl, NameDivideFloating> FunctionDivideFloating;
|
typedef FunctionBinaryArithmetic<DivideFloatingImpl, NameDivideFloating> FunctionDivideFloating;
|
||||||
typedef FunctionBinaryArithmetic<DivideIntegralImpl, NameDivideIntegral> FunctionDivideIntegral;
|
typedef FunctionBinaryArithmetic<DivideIntegralImpl, NameDivideIntegral> FunctionDivideIntegral;
|
||||||
|
typedef FunctionBinaryArithmetic<DivideIntegralOrZeroImpl, NameDivideIntegralOrZero> FunctionDivideIntegralOrZero;
|
||||||
typedef FunctionBinaryArithmetic<ModuloImpl, NameModulo> FunctionModulo;
|
typedef FunctionBinaryArithmetic<ModuloImpl, NameModulo> FunctionModulo;
|
||||||
typedef FunctionUnaryArithmetic<NegateImpl, NameNegate> FunctionNegate;
|
typedef FunctionUnaryArithmetic<NegateImpl, NameNegate> FunctionNegate;
|
||||||
typedef FunctionBinaryArithmetic<BitAndImpl, NameBitAnd> FunctionBitAnd;
|
typedef FunctionBinaryArithmetic<BitAndImpl, NameBitAnd> FunctionBitAnd;
|
||||||
|
@ -11,6 +11,7 @@ void registerFunctionsArithmetic(FunctionFactory & factory)
|
|||||||
factory.registerFunction<FunctionMultiply>();
|
factory.registerFunction<FunctionMultiply>();
|
||||||
factory.registerFunction<FunctionDivideFloating>();
|
factory.registerFunction<FunctionDivideFloating>();
|
||||||
factory.registerFunction<FunctionDivideIntegral>();
|
factory.registerFunction<FunctionDivideIntegral>();
|
||||||
|
factory.registerFunction<FunctionDivideIntegralOrZero>();
|
||||||
factory.registerFunction<FunctionModulo>();
|
factory.registerFunction<FunctionModulo>();
|
||||||
factory.registerFunction<FunctionNegate>();
|
factory.registerFunction<FunctionNegate>();
|
||||||
factory.registerFunction<FunctionBitAnd>();
|
factory.registerFunction<FunctionBitAnd>();
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
5
dbms/tests/queries/0_stateless/00081_int_div_or_zero.sql
Normal file
5
dbms/tests/queries/0_stateless/00081_int_div_or_zero.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
select intDivOrZero(0, 0) = 0;
|
||||||
|
select intDivOrZero(-128, -1) = 0;
|
||||||
|
select intDivOrZero(-127, -1) = 127;
|
||||||
|
select intDivOrZero(1, 1) = 1;
|
||||||
|
select intDivOrZero(4, 2) = 2;
|
Loading…
Reference in New Issue
Block a user