20 #include <cudf/detail/utilities/hash_functions.cuh>
21 #include <cudf/detail/utilities/release_assert.cuh>
27 #include <thrust/equal.h>
28 #include <thrust/swap.h>
29 #include <thrust/transform_reduce.h>
56 template <
typename Element>
57 __device__
weak_ordering compare_elements(Element lhs, Element rhs)
60 return weak_ordering::LESS;
61 }
else if (rhs < lhs) {
64 return weak_ordering::EQUIVALENT;
80 template <typename Element, std::enable_if_t<std::is_floating_point<Element>::value>* =
nullptr>
83 if (isnan(lhs) and isnan(rhs)) {
84 return weak_ordering::EQUIVALENT;
85 }
else if (isnan(rhs)) {
86 return weak_ordering::LESS;
87 }
else if (isnan(lhs)) {
91 return detail::compare_elements(lhs, rhs);
103 template <typename Element, std::enable_if_t<not std::is_floating_point<Element>::value>* =
nullptr>
106 return detail::compare_elements(lhs, rhs);
117 template <typename Element, std::enable_if_t<std::is_floating_point<Element>::value>* =
nullptr>
120 if (isnan(lhs) and isnan(rhs)) {
return true; }
132 template <typename Element, std::enable_if_t<not std::is_floating_point<Element>::value>* =
nullptr>
143 template <
bool has_nulls = true>
158 bool nulls_are_equal =
true)
159 : lhs{lhs}, rhs{rhs}, nulls_are_equal{nulls_are_equal}
170 template <
typename Element,
171 std::enable_if_t<cudf::is_equality_comparable<Element, Element>()>* =
nullptr>
172 __device__
bool operator()(size_type lhs_element_index, size_type rhs_element_index)
const
176 bool const lhs_is_null{lhs.nullable() and lhs.is_null(lhs_element_index)};
177 bool const rhs_is_null{rhs.nullable() and rhs.is_null(rhs_element_index)};
178 if (lhs_is_null and rhs_is_null) {
179 return nulls_are_equal;
180 }
else if (lhs_is_null != rhs_is_null) {
186 rhs.element<Element>(rhs_element_index));
189 template <
typename Element,
190 std::enable_if_t<not cudf::is_equality_comparable<Element, Element>()>* =
nullptr>
191 __device__
bool operator()(size_type lhs_element_index, size_type rhs_element_index)
193 release_assert(
false &&
"Attempted to compare elements of uncomparable types.");
198 column_device_view lhs;
199 column_device_view rhs;
200 bool nulls_are_equal;
203 template <
bool has_nulls = true>
207 : lhs{lhs}, rhs{rhs}, nulls_are_equal{nulls_are_equal}
209 CUDF_EXPECTS(lhs.num_columns() == rhs.num_columns(),
"Mismatched number of columns.");
212 __device__
bool operator()(size_type lhs_row_index, size_type rhs_row_index)
const noexcept
221 return thrust::equal(thrust::seq, lhs.begin(), lhs.end(), rhs.begin(), equal_elements);
227 bool nulls_are_equal;
235 template <
bool has_nulls = true>
252 : lhs{lhs}, rhs{rhs}, null_precedence{null_precedence}
266 template <
typename Element,
267 std::enable_if_t<cudf::is_relationally_comparable<Element, Element>()>* =
nullptr>
269 size_type rhs_element_index)
const noexcept
272 bool const lhs_is_null{lhs.nullable() and lhs.is_null(lhs_element_index)};
273 bool const rhs_is_null{rhs.nullable() and rhs.is_null(rhs_element_index)};
275 if (lhs_is_null and rhs_is_null) {
276 return weak_ordering::EQUIVALENT;
277 }
else if (lhs_is_null) {
280 }
else if (rhs_is_null) {
281 return (null_precedence == null_order::AFTER) ? weak_ordering::LESS
287 rhs.element<Element>(rhs_element_index));
290 template <
typename Element,
291 std::enable_if_t<not cudf::is_relationally_comparable<Element, Element>()>* =
nullptr>
294 release_assert(
false &&
"Attempted to compare elements of uncomparable types.");
295 return weak_ordering::LESS;
299 column_device_view lhs;
300 column_device_view rhs;
319 template <
bool has_nulls = true>
340 order const* column_order =
nullptr,
342 : _lhs{lhs}, _rhs{rhs}, _column_order{column_order}, _null_precedence{null_precedence}
345 CUDF_EXPECTS(_lhs.num_columns() == _rhs.num_columns(),
"Mismatched number of columns.");
357 __device__
bool operator()(size_type lhs_index, size_type rhs_index)
const noexcept
359 for (size_type i = 0; i < _lhs.num_columns(); ++i) {
360 bool ascending = (_column_order ==
nullptr) or (_column_order[i] == order::ASCENDING);
371 if (state == weak_ordering::EQUIVALENT) {
continue; }
382 order const* _column_order{};
391 template <
template <
typename>
class hash_function,
bool has_nulls =
true>
394 template <
typename T>
395 __device__
inline hash_value_type operator()(
column_device_view col, size_type row_index)
397 if (has_nulls && col.
is_null(row_index)) {
return std::numeric_limits<hash_value_type>::max(); }
399 return hash_function<T>{}(col.
element<T>(row_index));
403 template <
template <
typename>
class hash_function,
bool has_nulls =
true>
407 : _seed{0}, _null_hash(std::numeric_limits<hash_value_type>::max())
411 uint32_t seed = 0, hash_value_type null_hash = std::numeric_limits<hash_value_type>::max())
412 : _seed{seed}, _null_hash(null_hash)
416 template <
typename T>
417 __device__
inline hash_value_type operator()(
column_device_view col, size_type row_index)
419 if (has_nulls && col.
is_null(row_index)) {
return _null_hash; }
421 return hash_function<T>{_seed}(col.
element<T>(row_index));
426 hash_value_type _null_hash;
435 template <
template <
typename>
class hash_function,
bool has_nulls =
true>
441 __device__
auto operator()(size_type row_index)
const
443 auto hash_combiner = [](hash_value_type lhs, hash_value_type rhs) {
444 return hash_function<hash_value_type>{}.hash_combine(lhs, rhs);
448 auto hasher = [=](size_type column_index) {
451 _table.column(column_index),
456 return thrust::transform_reduce(thrust::seq,
457 thrust::make_counting_iterator(0),
458 thrust::make_counting_iterator(_table.num_columns()),
475 template <
template <
typename>
class hash_function,
bool has_nulls =
true>
480 : _table{t}, _initial_hash(initial_hash)
484 __device__
auto operator()(size_type row_index)
const
486 auto hash_combiner = [](hash_value_type lhs, hash_value_type rhs) {
487 return hash_function<hash_value_type>{}.hash_combine(lhs, rhs);
491 auto hasher = [=](size_type column_index) {
494 _table.column(column_index),
497 return hash_combiner(_initial_hash[column_index], hash_value);
501 return thrust::transform_reduce(thrust::seq,
502 thrust::make_counting_iterator(0),
503 thrust::make_counting_iterator(_table.num_columns()),
511 hash_value_type* _initial_hash;