diff --git a/cpp/include/cudf/ast/ast_operator.hpp b/cpp/include/cudf/ast/ast_operator.hpp index 2443829d1459..76678a13dcf7 100644 --- a/cpp/include/cudf/ast/ast_operator.hpp +++ b/cpp/include/cudf/ast/ast_operator.hpp @@ -26,21 +26,22 @@ namespace ast { */ enum class ast_operator : int32_t { // Binary operators - ADD, ///< operator + - SUB, ///< operator - - MUL, ///< operator * - DIV, ///< operator / using common type of lhs and rhs - TRUE_DIV, ///< operator / after promoting type to floating point - FLOOR_DIV, ///< operator / after promoting to the common type of lhs and rhs (integral or - ///< floating point), and then flooring the result - MOD, ///< operator % - PYMOD, ///< operator % using Python's sign rules for negatives - POW, ///< lhs ^ rhs - EQUAL, ///< operator == - NULL_EQUAL, ///< operator == with Spark rules: NULL_EQUAL(null, null) is true, NULL_EQUAL(null, - ///< valid) is false, and - ///< NULL_EQUAL(valid, valid) == EQUAL(valid, valid) - NOT_EQUAL, ///< operator != + ADD, ///< operator + + SUB, ///< operator - + MUL, ///< operator * + DIV, ///< operator / using common type of lhs and rhs + TRUE_DIV, ///< operator / after promoting type to floating point + FLOOR_DIV, ///< operator / after promoting to the common type of lhs and rhs (integral or + ///< floating point), and then flooring the result + MOD, ///< operator % + PYMOD, ///< operator % using Python's sign rules for negatives + POW, ///< lhs ^ rhs + EQUAL, ///< operator ==: returns NULL when either operand is NULL, otherwise returns whether they + ///< are equal + NULL_EQUAL, ///< null-safe equality (result is never null): returns true if both operands are + ///< null, false if one is null, otherwise returns whether they are equal + NOT_EQUAL, ///< operator !=: returns NULL when either operand is NULL, otherwise returns whether + ///< they are unequal LESS, ///< operator < GREATER, ///< operator > LESS_EQUAL, ///< operator <= @@ -48,16 +49,14 @@ enum class ast_operator : int32_t { BITWISE_AND, ///< operator & BITWISE_OR, ///< operator | BITWISE_XOR, ///< operator ^ - LOGICAL_AND, ///< operator && - NULL_LOGICAL_AND, ///< operator && with Spark rules: NULL_LOGICAL_AND(null, null) is null, - ///< NULL_LOGICAL_AND(null, true) is - ///< null, NULL_LOGICAL_AND(null, false) is false, and NULL_LOGICAL_AND(valid, - ///< valid) == LOGICAL_AND(valid, valid) - LOGICAL_OR, ///< operator || - NULL_LOGICAL_OR, ///< operator || with Spark rules: NULL_LOGICAL_OR(null, null) is null, - ///< NULL_LOGICAL_OR(null, true) is true, - ///< NULL_LOGICAL_OR(null, false) is null, and NULL_LOGICAL_OR(valid, valid) == - ///< LOGICAL_OR(valid, valid) + LOGICAL_AND, ///< operator &&: returns NULL when either operand is NULL, otherwise returns + ///< boolean AND of the two operands + NULL_LOGICAL_AND, ///< three-valued (Kleene) &&: if any operand is false, returns false; if both + ///< operands are true, returns true; otherwise returns null + LOGICAL_OR, ///< operator ||: returns NULL when either operand is NULL, otherwise returns boolean + ///< OR of the two operands + NULL_LOGICAL_OR, ///< three-valued (Kleene) ||: if any operand is true, returns true; if both + ///< operands are false, returns false; otherwise returns null // Unary operators IDENTITY, ///< Identity function IS_NULL, ///< Check if operand is null diff --git a/cpp/include/cudf/binaryop.hpp b/cpp/include/cudf/binaryop.hpp index e699d4d63bbb..c1e4e7fb8a2f 100644 --- a/cpp/include/cudf/binaryop.hpp +++ b/cpp/include/cudf/binaryop.hpp @@ -58,28 +58,34 @@ enum class binary_operator : int32_t { BITWISE_AND, ///< operator & BITWISE_OR, ///< operator | BITWISE_XOR, ///< operator ^ - LOGICAL_AND, ///< operator && - LOGICAL_OR, ///< operator || - EQUAL, ///< operator == - NOT_EQUAL, ///< operator != + LOGICAL_AND, ///< operator &&: returns NULL when either operand is NULL, otherwise + ///< returns boolean AND of the two operands + LOGICAL_OR, ///< operator ||: returns NULL when either operand is NULL, otherwise + ///< returns boolean OR of the two operands + EQUAL, ///< operator ==: returns NULL when either operand is NULL, otherwise + ///< returns whether they are equal + NOT_EQUAL, ///< operator !=: returns NULL when either operand is NULL, otherwise + ///< returns whether they are unequal LESS, ///< operator < GREATER, ///< operator > LESS_EQUAL, ///< operator <= GREATER_EQUAL, ///< operator >= - NULL_EQUALS, ///< Returns true when both operands are null; false when one is null; the - ///< result of equality when both are non-null - NULL_NOT_EQUALS, ///< Returns false when both operands are null; true when one is null; the - ///< result of inequality when both are non-null + NULL_EQUALS, ///< null-safe equality (result is never null): returns true if both + ///< operands are null, false if one is null, otherwise returns whether + ///< they are equal + NULL_NOT_EQUALS, ///< null-safe inequality (result is never null): returns false if both + ///< operands are null, true if one is null, otherwise returns whether + ///< they are unequal NULL_MAX, ///< Returns max of operands when both are non-null; returns the non-null ///< operand when one is null; or invalid when both are null NULL_MIN, ///< Returns min of operands when both are non-null; returns the non-null ///< operand when one is null; or invalid when both are null GENERIC_BINARY, ///< generic binary operator to be generated with input ///< ptx code - NULL_LOGICAL_AND, ///< operator && with Spark rules: (null, null) is null, (null, true) is null, - ///< (null, false) is false, and (valid, valid) == LOGICAL_AND(valid, valid) - NULL_LOGICAL_OR, ///< operator || with Spark rules: (null, null) is null, (null, true) is true, - ///< (null, false) is null, and (valid, valid) == LOGICAL_OR(valid, valid) + NULL_LOGICAL_AND, ///< three-valued (Kleene) &&: if any operand is false, returns false; if both + ///< operands are true, returns true; otherwise returns null + NULL_LOGICAL_OR, ///< three-valued (Kleene) ||: if any operand is true, returns true; if both + ///< operands are false, returns false; otherwise returns null INVALID_BINARY ///< invalid operation }; @@ -140,7 +146,9 @@ constexpr inline bool binary_op_has_common_type_v = * This distinction is significant in case of non-commutative binary operations * * Regardless of the operator, the validity of the output value is the logical - * AND of the validity of the two operands except NullMin and NullMax (logical OR). + * AND of the validity of the two operands, except NULL_MIN and NULL_MAX (logical + * OR), NULL_EQUALS and NULL_NOT_EQUALS (always valid), and NULL_LOGICAL_AND and + * NULL_LOGICAL_OR (see binary_operator). * * @param lhs The left operand scalar * @param rhs The right operand column @@ -171,7 +179,9 @@ std::unique_ptr binary_operation( * This distinction is significant in case of non-commutative binary operations * * Regardless of the operator, the validity of the output value is the logical - * AND of the validity of the two operands except NullMin and NullMax (logical OR). + * AND of the validity of the two operands, except NULL_MIN and NULL_MAX (logical + * OR), NULL_EQUALS and NULL_NOT_EQUALS (always valid), and NULL_LOGICAL_AND and + * NULL_LOGICAL_OR (see binary_operator). * * @param lhs The left operand column * @param rhs The right operand scalar @@ -200,7 +210,9 @@ std::unique_ptr binary_operation( * The output contains the result of `op(lhs[i], rhs[i])` for all `0 <= i < lhs.size()` * * Regardless of the operator, the validity of the output value is the logical - * AND of the validity of the two operands except NullMin and NullMax (logical OR). + * AND of the validity of the two operands, except NULL_MIN and NULL_MAX (logical + * OR), NULL_EQUALS and NULL_NOT_EQUALS (always valid), and NULL_LOGICAL_AND and + * NULL_LOGICAL_OR (see binary_operator). * * @param lhs The left operand column * @param rhs The right operand column diff --git a/java/src/main/java/ai/rapids/cudf/BinaryOp.java b/java/src/main/java/ai/rapids/cudf/BinaryOp.java index 7e1e460985ac..a8495f8fe7a3 100644 --- a/java/src/main/java/ai/rapids/cudf/BinaryOp.java +++ b/java/src/main/java/ai/rapids/cudf/BinaryOp.java @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ package ai.rapids.cudf; @@ -29,21 +29,28 @@ public enum BinaryOp { BITWISE_AND(16), BITWISE_OR(17), BITWISE_XOR(18), - LOGICAL_AND(19), - LOGICAL_OR(20), - EQUAL(21), - NOT_EQUAL(22), + LOGICAL_AND(19), // operator &&: returns NULL when either operand is NULL, otherwise returns + // boolean AND of the two operands + LOGICAL_OR(20), // operator ||: returns NULL when either operand is NULL, otherwise returns + // boolean OR of the two operands + EQUAL(21), // operator ==: returns NULL when either operand is NULL, otherwise returns + // whether they are equal + NOT_EQUAL(22), // operator !=: returns NULL when either operand is NULL, otherwise returns + // whether they are unequal LESS(23), GREATER(24), LESS_EQUAL(25), // <= GREATER_EQUAL(26), // >= - NULL_EQUALS(27), // like EQUAL but NULL == NULL is TRUE and NULL == not NULL is FALSE + NULL_EQUALS(27), // null-safe equality (result is never null): returns true if both operands are + // null, false if one is null, otherwise returns whether they are equal NULL_NOT_EQUALS(28), // negation of NULL_EQUALS NULL_MAX(29), // MAX but NULL < not NULL NULL_MIN(30), // MIN but NULL > not NULL //NOT IMPLEMENTED YET GENERIC_BINARY(30); - NULL_LOGICAL_AND(32), - NULL_LOGICAL_OR(33); + NULL_LOGICAL_AND(32), // three-valued (Kleene) &&: if any operand is false, returns false; if both + // operands are true, returns true; otherwise returns null + NULL_LOGICAL_OR(33); // three-valued (Kleene) ||: if any operand is true, returns true; if both + // operands are false, returns false; otherwise returns null static final EnumSet COMPARISON = EnumSet.of( diff --git a/java/src/main/java/ai/rapids/cudf/ast/BinaryOperator.java b/java/src/main/java/ai/rapids/cudf/ast/BinaryOperator.java index 80276f2642c3..eb0e936296e8 100644 --- a/java/src/main/java/ai/rapids/cudf/ast/BinaryOperator.java +++ b/java/src/main/java/ai/rapids/cudf/ast/BinaryOperator.java @@ -22,9 +22,12 @@ public enum BinaryOperator { MOD(6), // operator % PYMOD(7), // operator % using Python's sign rules for negatives POW(8), // lhs ^ rhs - EQUAL(9), // operator == - NULL_EQUAL(10), // operator == using Spark rules for null inputs - NOT_EQUAL(11), // operator != + EQUAL(9), // operator ==: returns NULL when either operand is NULL, otherwise returns + // whether they are equal + NULL_EQUAL(10), // null-safe equality (result is never null): returns true if both operands + // are null, false if one is null, otherwise returns whether they are equal + NOT_EQUAL(11), // operator !=: returns NULL when either operand is NULL, otherwise returns + // whether they are unequal LESS(12), // operator < GREATER(13), // operator > LESS_EQUAL(14), // operator <= @@ -32,10 +35,14 @@ public enum BinaryOperator { BITWISE_AND(16), // operator & BITWISE_OR(17), // operator | BITWISE_XOR(18), // operator ^ - LOGICAL_AND(19), // operator && - NULL_LOGICAL_AND(20), // operator && using Spark rules for null inputs - LOGICAL_OR(21), // operator || - NULL_LOGICAL_OR(22); // operator || using Spark rules for null inputs + LOGICAL_AND(19), // operator &&: returns NULL when either operand is NULL, otherwise returns + // boolean AND of the two operands + NULL_LOGICAL_AND(20), // three-valued (Kleene) &&: if any operand is false, returns false; if both + // operands are true, returns true; otherwise returns null + LOGICAL_OR(21), // operator ||: returns NULL when either operand is NULL, otherwise returns + // boolean OR of the two operands + NULL_LOGICAL_OR(22); // three-valued (Kleene) ||: if any operand is true, returns true; if both + // operands are false, returns false; otherwise returns null private final byte nativeId;