mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12: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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -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>
|
||||
struct ModuloImpl
|
||||
{
|
||||
@ -752,6 +780,7 @@ struct NameMinus { static constexpr auto name = "minus"; };
|
||||
struct NameMultiply { static constexpr auto name = "multiply"; };
|
||||
struct NameDivideFloating { static constexpr auto name = "divide"; };
|
||||
struct NameDivideIntegral { static constexpr auto name = "intDiv"; };
|
||||
struct NameDivideIntegralOrZero { static constexpr auto name = "intDivOrZero"; };
|
||||
struct NameModulo { static constexpr auto name = "modulo"; };
|
||||
struct NameNegate { static constexpr auto name = "negate"; };
|
||||
struct NameBitAnd { static constexpr auto name = "bitAnd"; };
|
||||
@ -766,6 +795,7 @@ typedef FunctionBinaryArithmetic<MinusImpl, NameMinus> FunctionMinus;
|
||||
typedef FunctionBinaryArithmetic<MultiplyImpl, NameMultiply> FunctionMultiply;
|
||||
typedef FunctionBinaryArithmetic<DivideFloatingImpl, NameDivideFloating> FunctionDivideFloating;
|
||||
typedef FunctionBinaryArithmetic<DivideIntegralImpl, NameDivideIntegral> FunctionDivideIntegral;
|
||||
typedef FunctionBinaryArithmetic<DivideIntegralOrZeroImpl, NameDivideIntegralOrZero> FunctionDivideIntegralOrZero;
|
||||
typedef FunctionBinaryArithmetic<ModuloImpl, NameModulo> FunctionModulo;
|
||||
typedef FunctionUnaryArithmetic<NegateImpl, NameNegate> FunctionNegate;
|
||||
typedef FunctionBinaryArithmetic<BitAndImpl, NameBitAnd> FunctionBitAnd;
|
||||
|
@ -11,6 +11,7 @@ void registerFunctionsArithmetic(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionMultiply>();
|
||||
factory.registerFunction<FunctionDivideFloating>();
|
||||
factory.registerFunction<FunctionDivideIntegral>();
|
||||
factory.registerFunction<FunctionDivideIntegralOrZero>();
|
||||
factory.registerFunction<FunctionModulo>();
|
||||
factory.registerFunction<FunctionNegate>();
|
||||
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