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,
98  MOD,
99  PYMOD,
100  POW,
101  EQUAL,
102  NULL_EQUAL,
105  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,
118  LOGICAL_OR,
119  NULL_LOGICAL_OR,
123  // 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
A expression referring to data from a column in a table.
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
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.
std::string get_column_name() const
Get the column name.
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
column_name_reference(std::string column_name)
Construct a new column name reference object.
A expression referring to data from a column in a table.
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.
cudf::data_type get_data_type(table_view const &left_table, table_view const &right_table) const
Get the data type.
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
cudf::data_type get_data_type(table_view const &table) const
Get the data type.
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
table_reference get_table_source() const
Get the table source.
column_reference(cudf::size_type column_index, table_reference table_source=table_reference::LEFT)
Construct a new column reference object.
cudf::size_type get_column_index() const
Get the column index.
A type-erased scalar_device_view where the value is a fixed width type or a string.
size_type const _size
Size of the string in bytes for string scalar.
generic_scalar_device_view(duration_scalar< T > &s)
Construct a new generic scalar device view object from a duration scalar.
generic_scalar_device_view(data_type type, void const *data, bool *is_valid)
Construct a new fixed width scalar device view object.
generic_scalar_device_view(string_scalar &s)
Construct a new generic scalar device view object from a string scalar.
generic_scalar_device_view(timestamp_scalar< T > &s)
Construct a new generic scalar device view object from a timestamp scalar.
void const * _data
Pointer to device memory containing the value.
generic_scalar_device_view(data_type type, void const *data, bool *is_valid, size_type size)
Construct a new string scalar device view object.
T const value() const noexcept
Returns the stored value.
generic_scalar_device_view(numeric_scalar< T > &s)
Construct a new generic scalar device view object from a numeric scalar.
A literal value used in an abstract syntax tree.
literal(cudf::numeric_scalar< T > &value)
Construct a new literal object.
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
generic_scalar_device_view get_value() const
Get the value object.
cudf::data_type get_data_type() const
Get the data type.
literal(cudf::string_scalar &value)
Construct a new literal object.
literal(cudf::duration_scalar< T > &value)
Construct a new literal object.
bool is_valid(rmm::cuda_stream_view stream) const
Check if the underlying scalar is valid.
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
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.
literal(cudf::timestamp_scalar< T > &value)
Construct a new literal object.
An operation expression holds an operator and zero or more operands.
std::vector< std::reference_wrapper< expression const > > get_operands() const
Get the operands.
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.
ast_operator get_operator() const
Get the operator.
operation(ast_operator op, expression const &left, expression const &right)
Construct a new binary operation object.
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
Accepts a visitor class.
operation(ast_operator op, expression const &input)
Construct a new unary operation object.
cudf::size_type accept(detail::expression_parser &visitor) const override
Accepts a visitor class.
Indicator for the logical data type of an element in a column.
Definition: types.hpp:227
A non-owning view of scalar from device that is trivially copyable and usable in CUDA device code.
bool is_valid() const noexcept
Returns whether the scalar holds a valid value (i.e., not null).
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.
data_type type() const noexcept
Returns the value type.
An owning class to represent a duration value in device memory.
Definition: scalar.hpp:679
An owning class to represent a numerical value in device memory.
Definition: scalar.hpp:243
An owning class to represent a singular value.
Definition: scalar.hpp:48
bool is_valid(rmm::cuda_stream_view stream=cudf::get_default_stream()) const
Indicates whether the scalar contains a valid value.
An owning class to represent a string in device memory.
Definition: scalar.hpp:429
A non-owning, immutable view of device data that is a variable length char array representing a UTF-8...
Definition: string_view.hpp:44
A set of cudf::column_view's of the same size.
Definition: table_view.hpp:187
A set of cudf::column's of the same size.
Definition: table.hpp:40
An owning class to represent a timestamp value in device memory.
Definition: scalar.hpp:624
#define CUDF_FAIL(...)
Indicates that an erroneous code path has been taken.
Definition: error.hpp:209
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:80
cuDF interfaces
Definition: aggregation.hpp:34
Class definitions for cudf::scalar.
Scalar device view class definitions.
A generic expression that can be evaluated to return a value.
Definition: expressions.hpp:41
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
virtual cudf::size_type accept(detail::expression_parser &visitor) const =0
Accepts a visitor class.
virtual std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const =0
Accepts a visitor class.
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.
Class definitions for (mutable)_table_view
Type declarations for libcudf.