expressions.hpp
1 /*
2  * Copyright (c) 2020-2023, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <cudf/scalar/scalar.hpp>
21 #include <cudf/types.hpp>
22 #include <cudf/utilities/error.hpp>
23 
24 #include <cstdint>
25 
26 namespace cudf {
27 namespace ast {
28 
29 // Forward declaration.
30 namespace detail {
31 class expression_parser;
32 class expression_transformer;
33 } // namespace detail
34 
41 struct expression {
48  virtual cudf::size_type accept(detail::expression_parser& visitor) const = 0;
49 
56  virtual std::reference_wrapper<expression const> accept(
57  detail::expression_transformer& visitor) const = 0;
58 
66  [[nodiscard]] bool may_evaluate_null(table_view const& left, rmm::cuda_stream_view stream) const
67  {
68  return may_evaluate_null(left, left, stream);
69  }
70 
79  [[nodiscard]] virtual bool may_evaluate_null(table_view const& left,
80  table_view const& right,
81  rmm::cuda_stream_view stream) const = 0;
82 
83  virtual ~expression() {}
84 };
85 
89 enum class ast_operator : int32_t {
90  // Binary operators
91  ADD,
92  SUB,
93  MUL,
94  DIV,
95  TRUE_DIV,
96  FLOOR_DIV,
97  MOD,
99  PYMOD,
100  POW,
101  EQUAL,
102  NULL_EQUAL,
103  NOT_EQUAL,
106  LESS,
107  GREATER,
108  LESS_EQUAL,
109  GREATER_EQUAL,
110  BITWISE_AND,
111  BITWISE_OR,
112  BITWISE_XOR,
113  LOGICAL_AND,
114  NULL_LOGICAL_AND,
115  LOGICAL_OR,
119  NULL_LOGICAL_OR,
120  // Unary operators
124  IDENTITY,
125  IS_NULL,
126  SIN,
127  COS,
128  TAN,
129  ARCSIN,
130  ARCCOS,
131  ARCTAN,
132  SINH,
133  COSH,
134  TANH,
135  ARCSINH,
136  ARCCOSH,
137  ARCTANH,
138  EXP,
139  LOG,
140  SQRT,
141  CBRT,
142  CEIL,
143  FLOOR,
144  ABS,
145  RINT,
146  BIT_INVERT,
147  NOT,
148  CAST_TO_INT64,
149  CAST_TO_UINT64,
150  CAST_TO_FLOAT64
151 };
152 
158 enum class table_reference {
159  LEFT,
160  RIGHT,
161  OUTPUT
162 };
163 
168  public:
175  template <typename T>
176  __device__ T const value() const noexcept
177  {
178  if constexpr (std::is_same_v<T, cudf::string_view>) {
179  return string_view(static_cast<char const*>(_data), _size);
180  }
181  return *static_cast<T const*>(_data);
182  }
183 
188  template <typename T>
190  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
191  {
192  }
193 
198  template <typename T>
200  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
201  {
202  }
203 
208  template <typename T>
210  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
211  {
212  }
213 
219  : generic_scalar_device_view(s.type(), s.data(), s.validity_data(), s.size())
220  {
221  }
222 
223  protected:
224  void const* _data{};
225  size_type const _size{};
226 
236  : cudf::detail::scalar_device_view_base(type, is_valid), _data(data)
237  {
238  }
239 
249  : cudf::detail::scalar_device_view_base(type, is_valid), _data(data), _size(size)
250  {
251  }
252 };
253 
257 class literal : public expression {
258  public:
265  template <typename T>
266  literal(cudf::numeric_scalar<T>& value) : scalar(value), value(value)
267  {
268  }
269 
276  template <typename T>
277  literal(cudf::timestamp_scalar<T>& value) : scalar(value), value(value)
278  {
279  }
280 
287  template <typename T>
288  literal(cudf::duration_scalar<T>& value) : scalar(value), value(value)
289  {
290  }
291 
297  literal(cudf::string_scalar& value) : scalar(value), value(value) {}
298 
304  [[nodiscard]] cudf::data_type get_data_type() const { return get_value().type(); }
305 
311  [[nodiscard]] generic_scalar_device_view get_value() const { return value; }
312 
316  cudf::size_type accept(detail::expression_parser& visitor) const override;
317 
321  std::reference_wrapper<expression const> accept(
322  detail::expression_transformer& visitor) const override;
323 
324  [[nodiscard]] bool may_evaluate_null(table_view const& left,
325  table_view const& right,
326  rmm::cuda_stream_view stream) const override
327  {
328  return !is_valid(stream);
329  }
330 
337  [[nodiscard]] bool is_valid(rmm::cuda_stream_view stream) const
338  {
339  return scalar.is_valid(stream);
340  }
341 
342  private:
343  cudf::scalar const& scalar;
344  generic_scalar_device_view const value;
345 };
346 
350 class column_reference : public expression {
351  public:
360  table_reference table_source = table_reference::LEFT)
361  : column_index(column_index), table_source(table_source)
362  {
363  }
364 
370  [[nodiscard]] cudf::size_type get_column_index() const { return column_index; }
371 
377  [[nodiscard]] table_reference get_table_source() const { return table_source; }
378 
385  [[nodiscard]] cudf::data_type get_data_type(table_view const& table) const
386  {
387  return table.column(get_column_index()).type();
388  }
389 
397  [[nodiscard]] cudf::data_type get_data_type(table_view const& left_table,
398  table_view const& right_table) const
399  {
400  auto const table = [&] {
401  if (get_table_source() == table_reference::LEFT) {
402  return left_table;
403  } else if (get_table_source() == table_reference::RIGHT) {
404  return right_table;
405  } else {
406  CUDF_FAIL("Column reference data type cannot be determined from unknown table.");
407  }
408  }();
409  return table.column(get_column_index()).type();
410  }
411 
415  cudf::size_type accept(detail::expression_parser& visitor) const override;
416 
420  std::reference_wrapper<expression const> accept(
421  detail::expression_transformer& visitor) const override;
422 
423  [[nodiscard]] bool may_evaluate_null(table_view const& left,
424  table_view const& right,
425  rmm::cuda_stream_view stream) const override
426  {
427  return (table_source == table_reference::LEFT ? left : right).column(column_index).has_nulls();
428  }
429 
430  private:
431  cudf::size_type column_index;
432  table_reference table_source;
433 };
434 
438 class operation : public expression {
439  public:
446  operation(ast_operator op, expression const& input);
447 
455  operation(ast_operator op, expression const& left, expression const& right);
456 
457  // operation only stores references to expressions, so it does not accept r-value
458  // references: the calling code must own the expressions.
459  operation(ast_operator op, expression&& input) = delete;
460  operation(ast_operator op, expression&& left, expression&& right) = delete;
461  operation(ast_operator op, expression&& left, expression const& right) = delete;
462  operation(ast_operator op, expression const& left, expression&& right) = delete;
463 
469  [[nodiscard]] ast_operator get_operator() const { return op; }
470 
476  std::vector<std::reference_wrapper<expression const>> get_operands() const { return operands; }
477 
481  cudf::size_type accept(detail::expression_parser& visitor) const override;
482 
486  std::reference_wrapper<expression const> accept(
487  detail::expression_transformer& visitor) const override;
488 
489  [[nodiscard]] bool may_evaluate_null(table_view const& left,
490  table_view const& right,
491  rmm::cuda_stream_view stream) const override
492  {
493  return std::any_of(operands.cbegin(),
494  operands.cend(),
495  [&left, &right, &stream](std::reference_wrapper<expression const> subexpr) {
496  return subexpr.get().may_evaluate_null(left, right, stream);
497  });
498  };
499 
500  private:
501  ast_operator const op;
502  std::vector<std::reference_wrapper<expression const>> const operands;
503 };
504 
509  public:
516  column_name_reference(std::string column_name) : column_name(std::move(column_name)) {}
517 
523  [[nodiscard]] std::string get_column_name() const { return column_name; }
524 
528  cudf::size_type accept(detail::expression_parser& visitor) const override;
529 
533  std::reference_wrapper<expression const> accept(
534  detail::expression_transformer& visitor) const override;
535 
536  [[nodiscard]] bool may_evaluate_null(table_view const& left,
537  table_view const& right,
538  rmm::cuda_stream_view stream) const override
539  {
540  return true;
541  }
542 
543  private:
544  std::string column_name;
545 };
546 
547 } // namespace ast
548 
549 } // namespace cudf
cudf::ast::column_reference::accept
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
cudf::ast::literal::literal
literal(cudf::duration_scalar< T > &value)
Construct a new literal object.
Definition: expressions.hpp:288
table_view.hpp
Class definitions for (mutable)_table_view
cudf::ast::expression::may_evaluate_null
virtual bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const =0
Returns true if the expression may evaluate to null.
cudf::timestamp_scalar
An owning class to represent a timestamp value in device memory.
Definition: scalar.hpp:624
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(timestamp_scalar< T > &s)
Construct a new generic scalar device view object from a timestamp scalar.
Definition: expressions.hpp:199
cudf::ast::expression::may_evaluate_null
bool may_evaluate_null(table_view const &left, rmm::cuda_stream_view stream) const
Returns true if the expression may evaluate to null.
Definition: expressions.hpp:66
cudf::ast::literal::get_data_type
cudf::data_type get_data_type() const
Get the data type.
Definition: expressions.hpp:304
cudf::ast::generic_scalar_device_view::_size
size_type const _size
Size of the string in bytes for string scalar.
Definition: expressions.hpp:225
cudf::ast::column_reference::get_data_type
cudf::data_type get_data_type(table_view const &table) const
Get the data type.
Definition: expressions.hpp:385
scalar.hpp
Class definitions for cudf::scalar.
cudf::size_type
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:80
cudf::ast::operation::operation
operation(ast_operator op, expression const &left, expression const &right)
Construct a new binary operation object.
cudf::ast::column_name_reference::get_column_name
std::string get_column_name() const
Get the column name.
Definition: expressions.hpp:523
cudf::ast::operation::get_operator
ast_operator get_operator() const
Get the operator.
Definition: expressions.hpp:469
types.hpp
Type declarations for libcudf.
cudf::string_view
A non-owning, immutable view of device data that is a variable length char array representing a UTF-8...
Definition: string_view.hpp:44
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(numeric_scalar< T > &s)
Construct a new generic scalar device view object from a numeric scalar.
Definition: expressions.hpp:189
rmm::cuda_stream_view
CUDF_FAIL
#define CUDF_FAIL(...)
Indicates that an erroneous code path has been taken.
Definition: error.hpp:209
cudf::ast::literal::accept
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(data_type type, void const *data, bool *is_valid)
Construct a new fixed width scalar device view object.
Definition: expressions.hpp:235
cudf::table
A set of cudf::column's of the same size.
Definition: table.hpp:40
cudf::ast::operation::may_evaluate_null
bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const override
Returns true if the expression may evaluate to null.
Definition: expressions.hpp:489
cudf::ast::column_reference::get_column_index
cudf::size_type get_column_index() const
Get the column index.
Definition: expressions.hpp:370
cudf::ast::column_reference::accept
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
cudf::ast::operation::operation
operation(ast_operator op, expression const &input)
Construct a new unary operation object.
cudf::ast::literal::literal
literal(cudf::string_scalar &value)
Construct a new literal object.
Definition: expressions.hpp:297
cudf::ast::column_reference::get_table_source
table_reference get_table_source() const
Get the table source.
Definition: expressions.hpp:377
cudf::scalar::is_valid
bool is_valid(rmm::cuda_stream_view stream=cudf::get_default_stream()) const
Indicates whether the scalar contains a valid value.
cudf::ast::column_reference::get_data_type
cudf::data_type get_data_type(table_view const &left_table, table_view const &right_table) const
Get the data type.
Definition: expressions.hpp:397
cudf::ast::column_name_reference::accept
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(duration_scalar< T > &s)
Construct a new generic scalar device view object from a duration scalar.
Definition: expressions.hpp:209
cudf::ast::column_name_reference::accept
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
cudf::duration_scalar
An owning class to represent a duration value in device memory.
Definition: scalar.hpp:679
cudf::ast::column_name_reference
A expression referring to data from a column in a table.
Definition: expressions.hpp:508
cudf::unary_operator::SIN
@ SIN
Trigonometric sine.
cudf::ast::expression
A generic expression that can be evaluated to return a value.
Definition: expressions.hpp:41
cudf::detail::scalar_device_view_base
A non-owning view of scalar from device that is trivially copyable and usable in CUDA device code.
Definition: scalar_device_view.cuh:33
cudf::ast::literal::get_value
generic_scalar_device_view get_value() const
Get the value object.
Definition: expressions.hpp:311
cudf::scalar
An owning class to represent a singular value.
Definition: scalar.hpp:48
cudf::ast::operation::accept
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
cudf::numeric_scalar
An owning class to represent a numerical value in device memory.
Definition: scalar.hpp:243
cudf::table_view
A set of cudf::column_view's of the same size.
Definition: table_view.hpp:187
cudf::data_type
Indicator for the logical data type of an element in a column.
Definition: types.hpp:228
cudf::ast::literal::literal
literal(cudf::numeric_scalar< T > &value)
Construct a new literal object.
Definition: expressions.hpp:266
cudf::ast::generic_scalar_device_view::value
T const value() const noexcept
Returns the stored value.
Definition: expressions.hpp:176
cudf
cuDF interfaces
Definition: aggregation.hpp:34
cudf::detail::scalar_device_view_base::is_valid
bool is_valid() const noexcept
Returns whether the scalar holds a valid value (i.e., not null).
Definition: scalar_device_view.cuh:50
cudf::ast::operation
An operation expression holds an operator and zero or more operands.
Definition: expressions.hpp:438
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(string_scalar &s)
Construct a new generic scalar device view object from a string scalar.
Definition: expressions.hpp:218
cudf::ast::generic_scalar_device_view::_data
void const * _data
Pointer to device memory containing the value.
Definition: expressions.hpp:224
cudf::ast::column_name_reference::column_name_reference
column_name_reference(std::string column_name)
Construct a new column name reference object.
Definition: expressions.hpp:516
cudf::weak_ordering::LESS
@ LESS
Indicates a is less than (ordered before) b
cudf::ast::column_name_reference::may_evaluate_null
bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const override
Returns true if the expression may evaluate to null.
Definition: expressions.hpp:536
cudf::ast::literal
A literal value used in an abstract syntax tree.
Definition: expressions.hpp:257
cudf::ast::column_reference::column_reference
column_reference(cudf::size_type column_index, table_reference table_source=table_reference::LEFT)
Construct a new column reference object.
Definition: expressions.hpp:359
cudf::ast::literal::may_evaluate_null
bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const override
Returns true if the expression may evaluate to null.
Definition: expressions.hpp:324
cudf::ast::operation::get_operands
std::vector< std::reference_wrapper< expression const > > get_operands() const
Get the operands.
Definition: expressions.hpp:476
cudf::ast::column_reference
A expression referring to data from a column in a table.
Definition: expressions.hpp:350
cudf::string_scalar
An owning class to represent a string in device memory.
Definition: scalar.hpp:429
cudf::ast::generic_scalar_device_view
A type-erased scalar_device_view where the value is a fixed width type or a string.
Definition: expressions.hpp:167
cudf::ast::expression::accept
virtual cudf::size_type accept(detail::expression_parser &visitor) const =0
Accepts a visitor class.
cudf::ast::column_reference::may_evaluate_null
bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const override
Returns true if the expression may evaluate to null.
Definition: expressions.hpp:423
cudf::detail::scalar_device_view_base::scalar_device_view_base
scalar_device_view_base(data_type type, bool *is_valid)
Construct a new scalar device view base object from a device pointer and a validity boolean.
Definition: scalar_device_view.cuh:72
scalar_device_view.cuh
Scalar device view class definitions.
cudf::ast::operation::accept
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
cudf::ast::expression::accept
virtual std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const =0
Accepts a visitor class.
cudf::detail::scalar_device_view_base::type
data_type type() const noexcept
Returns the value type.
Definition: scalar_device_view.cuh:42
cudf::ast::literal::accept
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
cudf::ast::literal::is_valid
bool is_valid(rmm::cuda_stream_view stream) const
Check if the underlying scalar is valid.
Definition: expressions.hpp:337
cudf::ast::literal::literal
literal(cudf::timestamp_scalar< T > &value)
Construct a new literal object.
Definition: expressions.hpp:277
error.hpp
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
generic_scalar_device_view(data_type type, void const *data, bool *is_valid, size_type size)
Construct a new string scalar device view object.
Definition: expressions.hpp:248