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

Divide #7

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/function/scalar/operators/arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -835,16 +835,29 @@ void MultiplyFun::RegisterFunction(BuiltinFunctions &set) {
//===--------------------------------------------------------------------===//
// / [divide]
//===--------------------------------------------------------------------===//
template <typename T>
T DivideImpl(T left, T right) {
// if (right == 0.0) {
// if (left == 0.0) {
// return std::numeric_limits<T>::quiet_NaN();
// }
// if ((left < 0.0) != (right < 0.0)) {
// return -std::numeric_limits<T>::infinity();
// }
// return std::numeric_limits<T>::infinity();
// }
T result = left / right;
return result;
}

template <>
float DivideOperator::Operation(float left, float right) {
auto result = left / right;
return result;
return DivideImpl(left, right);
}

template <>
double DivideOperator::Operation(double left, double right) {
auto result = left / right;
return result;
return DivideImpl(left, right);
}

template <>
Expand Down Expand Up @@ -955,9 +968,9 @@ static scalar_function_t GetBinaryFunctionIgnoreZero(PhysicalType type) {
void DivideFun::RegisterFunction(BuiltinFunctions &set) {
ScalarFunctionSet fp_divide("/");
fp_divide.AddFunction(ScalarFunction({LogicalType::FLOAT, LogicalType::FLOAT}, LogicalType::FLOAT,
GetBinaryFunctionIgnoreZero<DivideOperator>(PhysicalType::FLOAT)));
GetScalarBinaryFunction<DivideOperator>(PhysicalType::FLOAT)));
fp_divide.AddFunction(ScalarFunction({LogicalType::DOUBLE, LogicalType::DOUBLE}, LogicalType::DOUBLE,
GetBinaryFunctionIgnoreZero<DivideOperator>(PhysicalType::DOUBLE)));
GetScalarBinaryFunction<DivideOperator>(PhysicalType::DOUBLE)));
fp_divide.AddFunction(
ScalarFunction({LogicalType::INTERVAL, LogicalType::BIGINT}, LogicalType::INTERVAL,
BinaryScalarFunctionIgnoreZero<interval_t, int64_t, interval_t, DivideOperator>));
Expand Down
13 changes: 13 additions & 0 deletions src/include/duckdb/function/cast/vector_cast_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,25 @@ struct VectorDecimalCastData {
uint8_t scale;
};

template <typename T>
bool IsFloatingAndNan(T value) {
if (!std::is_floating_point<T>::value) {
return false;
}
return Value::IsNan(value);
}

template <class OP>
struct VectorDecimalCastOperator {
template <class INPUT_TYPE, class RESULT_TYPE>
static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
auto data = reinterpret_cast<VectorDecimalCastData *>(dataptr);
RESULT_TYPE result_value;

if (IsFloatingAndNan(input)) {
mask.SetInvalid(idx);
return {};
}
if (!OP::template Operation<INPUT_TYPE, RESULT_TYPE>(input, result_value, data->vector_cast_data.parameters,
data->width, data->scale)) {
return HandleVectorCastError::Operation<RESULT_TYPE>("Failed to cast decimal value", mask, idx,
Expand Down
2 changes: 1 addition & 1 deletion test/issues/rigger/complex_division.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ SELECT c0, c1 FROM t0;
query III
SELECT c0, c1, ((t0.c0)::varchar!~(((t0.c0)/(t0.c1)))::varchar) FROM t0;
----
0.5 0 NULL
0.5 0 true
0.5 1 false
0.5 NULL NULL
0.5 NULL NULL
Expand Down
3 changes: 1 addition & 2 deletions test/issues/rigger/division_by_zero_null.test
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ COMMIT;
query II
SELECT t0.c1, (1/t0.c1) IS NULL FROM t0;
----
0.0 1
0.0 0
NULL 1

query I
SELECT t0.c1 FROM t0 WHERE (((1/(t0.c1))) IS NULL);
----
0.0
NULL

statement ok
Expand Down
15 changes: 5 additions & 10 deletions test/sql/function/numeric/test_fdiv_fmod.test
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,30 @@ NULL
NULL
NULL

# fmod by 0 results in NULL: should be NaN (if supported)
query I
SELECT fmod(42, 0)
----
NULL
nan

# fmod 0 by 0 results in NULL: should be NaN (if supported)
query I
SELECT fmod(0, 0)
----
NULL
nan

# fdiv by 0 results in NULL: should be Inf (if supported)
query I
SELECT fdiv(42, 0)
----
NULL
inf

# fdiv by 0 results in NULL: should be -Inf (if supported)
query I
SELECT fdiv(-42, 0)
----
NULL
-inf

# fdiv 0 by 0 results in NULL: should be NaN (if supported)
query I
SELECT fdiv(0, 0)
----
NULL
nan

query R
SELECT fmod(12.3456789, 5)
Expand Down
2 changes: 1 addition & 1 deletion test/sql/optimizer/expression/test_nop_arithmetic.test
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ NULL
query I
SELECT 0 / rowid FROM test
----
NULL
nan
0
35 changes: 35 additions & 0 deletions test/sql/types/float/divide_by_zero.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# name: test/sql/types/float/divide_by_zero.test
# description: Test behaviour of division by zero
# group: [float]

statement ok
PRAGMA enable_verification

foreach type FLOAT DOUBLE

query I
select (1)::${type} / (0)::${type};
----
inf

query I
select (-1)::${type} / (0)::${type};
----
-inf

query I
select (1)::${type} / ('-0')::${type};
----
-inf

query I
select ('-1')::${type} / ('-0')::${type};
----
inf

query I
select (0)::${type} / (0)::${type};
----
nan

endloop
18 changes: 16 additions & 2 deletions test/sql/types/float/nan_cast.test
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ foreach source_type FLOAT DOUBLE

foreach target_type <integral> DECIMAL(4,1) DECIMAL(9,1) DECIMAL(18,1) DECIMAL(38,1)

foreach val nan inf -inf
foreach val inf -inf

statement ok
SELECT '${val}'::${source_type}

# cannot cast nan, inf or -inf to these types
# cannot cast inf or -inf to these types
statement error
SELECT '${val}'::${source_type}::${target_type}
----
Expand All @@ -26,6 +26,20 @@ endloop

endloop

# casting nan to DECIMAL results in NULL
foreach source_type FLOAT DOUBLE

foreach target_type DECIMAL(4,1) DECIMAL(9,1) DECIMAL(18,1) DECIMAL(38,1)

query I
SELECT 'nan'::${source_type}::${target_type}
----
NULL

endloop

endloop

# we can cast nan, inf and -inf between floats and doubles, as well as to/from strings
foreach source_type FLOAT DOUBLE VARCHAR

Expand Down
6 changes: 3 additions & 3 deletions test/sql/types/null/test_null.test
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ NULL

# division by zero
query I
SELECT 4 / 0
SELECT 4::INT // 0::INT
----
NULL

Expand Down Expand Up @@ -64,15 +64,15 @@ NULL

# division by constant zero is NULL
query I
SELECT a / 0 FROM test;
SELECT a // 0 FROM test;
----
NULL
NULL
NULL

# division by non-constant zero as well
query I
SELECT a / (a - a) FROM test;
SELECT a // (a - a) FROM test;
----
NULL
NULL
Expand Down
Loading