Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
38de09b
feat(fixed_point): optional sticky overflow tracking on doing decimal…
Avinash-Raj May 2, 2026
cb1e7c9
feat(fixed_point): NTTP-based opt-in overflow tracking with decimal*_…
Avinash-Raj May 5, 2026
927fe61
Track float→decimal overflow for decimal*_safe
Avinash-Raj May 7, 2026
6a33a77
feat(binaryop): add binary_operation_safe with device overflow flag f…
Avinash-Raj May 11, 2026
281dce6
reverted modifications to fixed_point class and introduced free funct…
Avinash-Raj May 16, 2026
063f1d7
Merge branch 'main' into avi/decimal-overflow
Avinash-Raj May 16, 2026
f874b5e
introduced compile-time branching in convert-float-to-integer functio…
Avinash-Raj May 22, 2026
d738fe8
Fix -INT_MIN UB in convert_floating_to_integral and unify sign-reapply
Avinash-Raj May 23, 2026
736169f
Return per-row overflow column from binary_operation_safe
Avinash-Raj May 26, 2026
e378183
Make multiply_power10_saturating O(1) by precomputing the overflow th…
Avinash-Raj May 27, 2026
0e0d29c
Revert unrelated changes to binary_ops.cuh
Avinash-Raj May 27, 2026
ad57bd8
fixed_point: restore IIFE form in convert_floating_to_fixed
Avinash-Raj May 27, 2026
2cb1ace
Added floating conversion overflow tests
Avinash-Raj May 27, 2026
69095e1
Plumb mr through binary_operation_safe for exec_policy_nosync
Avinash-Raj Jun 1, 2026
eee3690
Merge branch 'main' into avi/decimal-overflow
Avinash-Raj Jun 1, 2026
73b68f8
Merge branch 'avi/decimal-overflow' of github.com:Avinash-Raj/cudf in…
Avinash-Raj Jun 1, 2026
72b132a
Addressed all the comments written by CodeRabbit
Avinash-Raj Jun 1, 2026
a585cfa
fix ci-styles
Avinash-Raj Jun 1, 2026
670af6c
Merge branch 'main' into avi/decimal-overflow
Avinash-Raj Jun 2, 2026
98dda38
Restore Rep return type in convert_floating_to_integral_shifting for …
Avinash-Raj Jun 2, 2026
9e5d015
Skip arithmetic on the overflow path in safe_* fixed-point primitives
Avinash-Raj Jun 3, 2026
c237180
Merge branch 'main' into avi/decimal-overflow
Avinash-Raj Jun 4, 2026
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
2 changes: 1 addition & 1 deletion cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ mark_as_advanced(CUDF_BUILD_STREAMS_TEST_UTIL)
option(CUDF_CLANG_TIDY "Enable clang-tidy during compilation" OFF)
option(CUDF_IWYU "Enable IWYU during compilation" OFF)
option(CUDF_CLANG_TIDY_AUTOFIX "Enable clang-tidy autofixes" OFF)

option(
CUDF_KVIKIO_REMOTE_IO
"Enable remote IO (e.g. AWS S3) support through KvikIO. If disabled, cudf-python will still be able to do remote IO through fsspec."
Expand Down Expand Up @@ -452,6 +451,7 @@ add_library(
src/binaryop/compiled/Sub.cu
src/binaryop/compiled/TrueDiv.cu
src/binaryop/compiled/binary_ops.cu
src/binaryop/compiled/binary_ops_safe.cu
src/binaryop/compiled/equality_ops.cu
src/binaryop/compiled/util.cpp
src/labeling/label_bins.cu
Expand Down
128 changes: 127 additions & 1 deletion cpp/include/cudf/binaryop.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

Expand All @@ -10,7 +10,9 @@
#include <cudf/utilities/export.hpp>
#include <cudf/utilities/memory_resource.hpp>

#include <cstdint>
#include <memory>
#include <utility>

namespace CUDF_EXPORT cudf {

Expand Down Expand Up @@ -221,6 +223,130 @@ std::unique_ptr<column> binary_operation(
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());

/**
* @brief Decimal fixed-point binary operation between a scalar and a column,
* with a per-row overflow column.
*
* The result column contains `op(lhs, rhs[i])` for all `0 <= i < rhs.size()`,
* matching the semantics of `binary_operation` for the seven supported decimal
* arithmetic operators (ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD).
*
* Additionally returns a `BOOL8` column of the same length as the result.
* Element `i` is `true` iff row `i` is an active (non-null on both sides) row
* whose arithmetic or rescale to @p output_type overflowed (or, for DIV / MOD
* / PMOD / PYMOD, divided by zero). Null rows and clean rows hold `false`.
* The overflow column has no null mask.
*
* @p lhs, @p rhs, and @p output_type must share the same decimal storage type
* (e.g. all `DECIMAL64`); mixing decimal widths or pairing decimal with a
* non-decimal operand is not supported on this path.
*
* @param lhs The left operand decimal scalar
* @param rhs The right operand decimal column
* @param op The binary operator
* @param output_type The desired data type of the result column (must be a base-10 decimal)
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned columns' device memory
* @return A pair `{result, overflow}` where `result` is the arithmetic result column and
* `overflow` is the per-row `BOOL8` overflow column described above.
* @throw cudf::logic_error if @p lhs or @p rhs is not a fixed-point type
* @throw cudf::logic_error if @p op is not one of ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD
* @throw cudf::logic_error if @p lhs, @p rhs, and @p output_type do not share the same
* decimal storage type
* @throw cudf::data_type_error if the operation is not supported for the types of
* @p lhs and @p rhs
*/
std::pair<std::unique_ptr<column>, std::unique_ptr<column>> binary_operation_safe(

@PointKernel PointKernel Jun 2, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compared to ansi, I do like the safe naming though it's not perfect.

Actually, safe is probably not a great choice either as we already have existing uses of unsafe to denote an operation is not thread safe, e.g. https://github.com/rapidsai/cudf/blob/4162d61633c332be91851126df388fb6489aac9c/cpp/include/cudf/utilities/bit.hpp#L73

AFAIK, we currently have three different naming schemes in libcudf related to overflow checking:

  1. For aggregation, we use _WITH_OVERFLOW suffix to denote it has overflow check https://github.com/rapidsai/cudf/blob/aa3cdee199d636d0075b6ae165d8ed09aff0b92a/cpp/include/cudf/aggregation.hpp#L81
  2. For JIT operators, we use the SQL term ansi, e.g. https://github.com/rapidsai/cudf/blob/6f8c429d0a532bdfd5d5e4057643addec6f5f486/cpp/include/cudf/detail/operators/ansi_arithmetic.cuh#L32
  3. The current effort with safe prefix/suffix

We should really converge on a consistent naming scheme going forward to avoid further fragmentation and branching.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we've agreed on using an "_overflow" suffix

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another minor difference I wanted to mention: in the SUM_WITH_OVERFLOW aggregation, both reduce and groupby currently return a single STRUCT column, where the first field is the sum and the second is the overflow flag.

It would be good to align with the existing pattern, or at least converge on a consistent one. That said, it’s not immediately obvious how to adjust the groupby or reduce code paths, since the input-output mapping assumes one input column projects to one output column, and there’s no straightforward way to change that.

Changing the output here from two columns to a single struct column seems relatively straightforward, but I’m not sure how important this consistency is in practice, or whether it’s worth enforcing it across the board.

scalar const& lhs,
column_view const& rhs,
binary_operator op,
data_type output_type,
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());

/**
* @brief Decimal fixed-point binary operation between a column and a scalar,
* with a per-row overflow column.
*
* The result column contains `op(lhs[i], rhs)` for all `0 <= i < lhs.size()`,
* matching the semantics of `binary_operation` for the seven supported decimal
* arithmetic operators (ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD).
*
* Additionally returns a `BOOL8` column of the same length as the result.
* Element `i` is `true` iff row `i` is an active (non-null on both sides) row
* whose arithmetic or rescale to @p output_type overflowed (or, for DIV / MOD
* / PMOD / PYMOD, divided by zero). Null rows and clean rows hold `false`.
* The overflow column has no null mask.
*
* @p lhs, @p rhs, and @p output_type must share the same decimal storage type
* (e.g. all `DECIMAL64`); mixing decimal widths or pairing decimal with a
* non-decimal operand is not supported on this path.
*
* @param lhs The left operand decimal column
* @param rhs The right operand decimal scalar
* @param op The binary operator
* @param output_type The desired data type of the result column (must be a base-10 decimal)
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned columns' device memory
* @return A pair `{result, overflow}` where `result` is the arithmetic result column and
* `overflow` is the per-row `BOOL8` overflow column described above.
* @throw cudf::logic_error if @p lhs or @p rhs is not a fixed-point type
* @throw cudf::logic_error if @p op is not one of ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD
* @throw cudf::logic_error if @p lhs, @p rhs, and @p output_type do not share the same
* decimal storage type
* @throw cudf::data_type_error if the operation is not supported for the types of
* @p lhs and @p rhs
*/
std::pair<std::unique_ptr<column>, std::unique_ptr<column>> binary_operation_safe(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this behaviour part of binary_operation instead?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What behavior are you referring to?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the error checking. rather than having binary_operation and binary_operation_safe, we should have a single binary_operation with enums to specify whether to check for errors.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this suggestion.

column_view const& lhs,
scalar const& rhs,
binary_operator op,
data_type output_type,
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());

/**
* @brief Decimal fixed-point binary operation between two columns,
* with a per-row overflow column.
*
* The result column contains `op(lhs[i], rhs[i])` for all `0 <= i < lhs.size()`,
* matching the semantics of `binary_operation` for the seven supported decimal
* arithmetic operators (ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD).
*
* Additionally returns a `BOOL8` column of the same length as the result.
* Element `i` is `true` iff row `i` is an active (non-null on both sides) row
* whose arithmetic or rescale to @p output_type overflowed (or, for DIV / MOD
* / PMOD / PYMOD, divided by zero). Null rows and clean rows hold `false`.
* The overflow column has no null mask.
*
* @p lhs, @p rhs, and @p output_type must share the same decimal storage type
* (e.g. all `DECIMAL64`); mixing decimal widths or pairing decimal with a
* non-decimal operand is not supported on this path.
*
* @param lhs The left operand decimal column
* @param rhs The right operand decimal column
* @param op The binary operator
* @param output_type The desired data type of the result column (must be a base-10 decimal)
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned columns' device memory
* @return A pair `{result, overflow}` where `result` is the arithmetic result column and
* `overflow` is the per-row `BOOL8` overflow column described above.
* @throw cudf::logic_error if @p lhs and @p rhs are different sizes
* @throw cudf::logic_error if @p lhs or @p rhs is not a fixed-point type
* @throw cudf::logic_error if @p op is not one of ADD, SUB, MUL, DIV, MOD, PMOD, PYMOD
* @throw cudf::logic_error if @p lhs, @p rhs, and @p output_type do not share the same
* decimal storage type
* @throw cudf::data_type_error if the operation is not supported for the types of
* @p lhs and @p rhs
*/
std::pair<std::unique_ptr<column>, std::unique_ptr<column>> binary_operation_safe(
column_view const& lhs,
column_view const& rhs,
binary_operator op,
data_type output_type,
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* @brief Performs a binary operation between two columns using a
* user-defined PTX function.
Expand Down
Loading
Loading