Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add moduloOrZero #9358

Merged
merged 5 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions dbms/src/Functions/intDiv.h → dbms/src/Functions/DivisionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,22 @@ struct DivideIntegralImpl
#endif
};

template <typename A, typename B>
struct ModuloImpl
{
using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
static const constexpr bool allow_fixed_string = false;

template <typename Result = ResultType>
static inline Result apply(A a, B b)
{
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
}

#if USE_EMBEDDED_COMPILER
static constexpr bool compilable = false; /// don't know how to throw from LLVM IR
#endif
};

}
2 changes: 1 addition & 1 deletion dbms/src/Functions/FunctionBinaryArithmetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <Columns/ColumnAggregateFunction.h>
#include "IFunctionImpl.h"
#include "FunctionHelpers.h"
#include "intDiv.h"
#include "DivisionUtils.h"
#include "castTypeToEither.h"
#include "FunctionFactory.h"
#include <Common/typeid_cast.h>
Expand Down
1 change: 0 additions & 1 deletion dbms/src/Functions/intDiv.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionBinaryArithmetic.h>
#include <Functions/intDiv.h>

#ifdef __SSE2__
#define LIBDIVIDE_USE_SSE2 1
Expand Down
2 changes: 0 additions & 2 deletions dbms/src/Functions/intDivOrZero.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionBinaryArithmetic.h>

#include "intDiv.h"


namespace DB
{
Expand Down
23 changes: 1 addition & 22 deletions dbms/src/Functions/modulo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,7 @@
namespace DB
{

namespace ErrorCodes
{
extern const int ILLEGAL_DIVISION;
}

template <typename A, typename B>
struct ModuloImpl
{
using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
static const constexpr bool allow_fixed_string = false;

template <typename Result = ResultType>
static inline Result apply(A a, B b)
{
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
}

#if USE_EMBEDDED_COMPILER
static constexpr bool compilable = false; /// don't know how to throw from LLVM IR
#endif
};
/// Optimizations for integer modulo by a constant.

template <typename A, typename B>
struct ModuloByConstantImpl
Expand Down
36 changes: 36 additions & 0 deletions dbms/src/Functions/moduloOrZero.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionBinaryArithmetic.h>


namespace DB
{

template <typename A, typename B>
struct ModuloOrZeroImpl
{
using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
static const constexpr bool allow_fixed_string = false;

template <typename Result = ResultType>
static inline Result apply(A a, B b)
{
if (unlikely(divisionLeadsToFPE(a, b)))
return 0;

return ModuloImpl<A, B>::template apply<Result>(a, b);
}

#if USE_EMBEDDED_COMPILER
static constexpr bool compilable = false; /// TODO implement the checks
#endif
};

struct NameModuloOrZero { static constexpr auto name = "moduloOrZero"; };
using FunctionModuloOrZero = FunctionBinaryArithmetic<ModuloOrZeroImpl, NameModuloOrZero>;

void registerFunctionModuloOrZero(FunctionFactory & factory)
{
factory.registerFunction<FunctionModuloOrZero>();
}

}
2 changes: 2 additions & 0 deletions dbms/src/Functions/registerFunctionsArithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ void registerFunctionDivide(FunctionFactory & factory);
void registerFunctionIntDiv(FunctionFactory & factory);
void registerFunctionIntDivOrZero(FunctionFactory & factory);
void registerFunctionModulo(FunctionFactory & factory);
void registerFunctionModuloOrZero(FunctionFactory & factory);
void registerFunctionNegate(FunctionFactory & factory);
void registerFunctionAbs(FunctionFactory & factory);
void registerFunctionBitAnd(FunctionFactory & factory);
Expand Down Expand Up @@ -49,6 +50,7 @@ void registerFunctionsArithmetic(FunctionFactory & factory)
registerFunctionIntDiv(factory);
registerFunctionIntDivOrZero(factory);
registerFunctionModulo(factory);
registerFunctionModuloOrZero(factory);
registerFunctionNegate(factory);
registerFunctionAbs(factory);
registerFunctionBitAnd(factory);
Expand Down
2 changes: 2 additions & 0 deletions dbms/tests/performance/arithmetic.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
<value>multiply</value>
<value>divide</value>
<value>intDivOrZero</value>
<value>modulo</value>
<value>moduloOrZero</value>
</values>
</substitution>
</substitutions>
Expand Down
5 changes: 5 additions & 0 deletions dbms/tests/queries/0_stateless/01086_modulo_or_zero.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1
1
1
1
1
5 changes: 5 additions & 0 deletions dbms/tests/queries/0_stateless/01086_modulo_or_zero.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
select moduloOrZero(0, 0) = 0;
select moduloOrZero(-128, -1) = 0;
select moduloOrZero(-127, -1) = 0;
select moduloOrZero(1, 1) = 0;
select moduloOrZero(5, 3) = 2;
4 changes: 4 additions & 0 deletions docs/en/query_language/functions/arithmetic_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ If arguments are floating-point numbers, they are pre-converted to integers by d
The remainder is taken in the same sense as in C++. Truncated division is used for negative numbers.
An exception is thrown when dividing by zero or when dividing a minimal negative number by minus one.

## moduloOrZero(a, b)

Differs from 'modulo' in that it returns zero when the divisor is zero.

## negate(a), -a operator

Calculates a number with the reverse sign. The result is always signed.
Expand Down