diff --git a/cpp/src/lists/copying/scatter_helper.cu b/cpp/src/lists/copying/scatter_helper.cu index 160a7bb23a94..7bcf08dd9c02 100644 --- a/cpp/src/lists/copying/scatter_helper.cu +++ b/cpp/src/lists/copying/scatter_helper.cu @@ -245,9 +245,8 @@ struct list_child_constructor { auto row_index = d_list_vector[list_index].row_index(); auto actual_list_row = d_list_vector[list_index].bind_to_column(source_lists, target_lists); auto lists_column = actual_list_row.get_column(); - auto lists_offsets_ptr = lists_column.offsets().template data(); auto child_strings_column = lists_column.child(); - auto strings_offset = lists_offsets_ptr[row_index] + intra_index; + auto strings_offset = lists_column.offset_at(row_index) + intra_index; if (child_strings_column.is_null(strings_offset)) { return null_string_view; } auto const d_str = child_strings_column.template element(strings_offset); @@ -313,11 +312,10 @@ struct list_child_constructor { auto actual_list_row = d_list_vector[list_index].bind_to_column(source_lists, target_lists); auto lists_column = actual_list_row.get_column(); auto child_lists_column = lists_column.child(); - auto lists_offsets_ptr = lists_column.offsets().template data(); auto child_lists_offsets_ptr = child_lists_column.child(lists_column_view::offsets_column_index) .template data(); - auto child_row_index = lists_offsets_ptr[row_index] + intra_index; + auto child_row_index = lists_column.offset_at(row_index) + intra_index; auto size = child_lists_offsets_ptr[child_row_index + 1] - child_lists_offsets_ptr[child_row_index]; return unbound_list_view{label, child_row_index, size}; @@ -389,13 +387,14 @@ struct list_child_constructor { cudf::size_type const& structs_list_num_rows, column_view const& structs_list_offsets, bitmask_type const* structs_list_nullmask, - cudf::size_type const& structs_list_null_count) { + cudf::size_type const& structs_list_null_count, + cudf::size_type const& structs_list_offset) { return lists_column_view(column_view(data_type{type_id::LIST}, structs_list_num_rows, nullptr, structs_list_nullmask, structs_list_null_count, - 0, + structs_list_offset, {structs_list_offsets, structs_member})); }; @@ -405,7 +404,8 @@ struct list_child_constructor { source_lists_column_view.size(), source_lists_column_view.offsets(), source_lists_column_view.null_mask(), - source_lists_column_view.null_count()); + source_lists_column_view.null_count(), + source_lists_column_view.offset()); }); auto const iter_target_member_as_list = @@ -414,7 +414,8 @@ struct list_child_constructor { target_lists_column_view.size(), target_lists_column_view.offsets(), target_lists_column_view.null_mask(), - target_lists_column_view.null_count()); + target_lists_column_view.null_count(), + target_lists_column_view.offset()); }); std::transform(iter_source_member_as_list, diff --git a/cpp/tests/copying/scatter_list_tests.cpp b/cpp/tests/copying/scatter_list_tests.cpp index 083e5fecf680..8a4bc864cda7 100644 --- a/cpp/tests/copying/scatter_list_tests.cpp +++ b/cpp/tests/copying/scatter_list_tests.cpp @@ -75,6 +75,82 @@ TYPED_TEST(TypedScatterListsTest, SlicedInputLists) cudf::test::lists_column_wrapper{{8, 8, 8}, {2, 2}, {9, 9, 9, 9}, {4, 4}, {5, 5}}); } +TYPED_TEST(TypedScatterListsTest, SlicedInputListsOfLists) +{ + using T = TypeParam; + + auto src_list_column = + cudf::test::lists_column_wrapper{ + {{{0, 0}, {9, 9}}, {{1, 1}, {8, 8}}, {{2, 2}, {7, 7}}, {{3, 3}, {6, 6}}}, + cudf::test::iterators::null_at(2)} + .release(); + auto src_sliced = cudf::slice(src_list_column->view(), {1, 4}).front(); + + auto target_list_column = cudf::test::lists_column_wrapper{{{9, 9}, {8, 8}, {7, 7}}, + {{6, 6}, {5, 5}, {4, 4}}, + {{3, 3}, {2, 2}, {1, 1}}, + {{9, 9}, {8, 8}, {7, 7}}, + {{6, 6}, {5, 5}, {4, 4}}, + {{3, 3}, {2, 2}, {1, 1}}}; + + auto scatter_map = cudf::test::fixed_width_column_wrapper{2, 0}; + + auto ret = cudf::scatter( + cudf::table_view({src_sliced}), scatter_map, cudf::table_view({target_list_column})); + + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + cudf::test::lists_column_wrapper{{{}, + {{6, 6}, {5, 5}, {4, 4}}, + {{1, 1}, {8, 8}}, + {{9, 9}, {8, 8}, {7, 7}}, + {{6, 6}, {5, 5}, {4, 4}}, + {{3, 3}, {2, 2}, {1, 1}}}, + cudf::test::iterators::null_at(0)}, + ret->get_column(0)); +} + +TYPED_TEST(TypedScatterListsTest, SlicedInputListsOfStructs) +{ + using T = TypeParam; + using offsets_column = cudf::test::fixed_width_column_wrapper; + using numerics_column = cudf::test::fixed_width_column_wrapper; + + auto src_numerics = numerics_column{0, 1, 2, 3}; + auto src_structs = cudf::test::structs_column_wrapper{{src_numerics}}; + auto src_validity = cudf::test::iterators::null_at(2); + auto [src_mask, src_null_count] = + cudf::test::detail::make_null_mask(src_validity, src_validity + 3); + auto src_list_column = cudf::make_lists_column(3, + offsets_column{0, 2, 4, 4}.release(), + src_structs.release(), + src_null_count, + std::move(src_mask)); + auto src_sliced = cudf::slice(src_list_column->view(), {1, 3}).front(); + + auto tgt_numerics = numerics_column{0, 1, 2, 3, 4}; + auto tgt_structs = cudf::test::structs_column_wrapper{{tgt_numerics}}; + auto target_list_column = cudf::make_lists_column( + 5, offsets_column{0, 1, 2, 3, 4, 5}.release(), tgt_structs.release(), 0, {}); + + auto scatter_map = cudf::test::fixed_width_column_wrapper{2, 0}; + + auto ret = cudf::scatter( + cudf::table_view({src_sliced}), scatter_map, cudf::table_view({target_list_column->view()})); + + auto expected_numerics = numerics_column{1, 2, 3, 3, 4}; + auto expected_structs = cudf::test::structs_column_wrapper{{expected_numerics}}; + auto expected_validity = cudf::test::iterators::null_at(0); + auto [expected_mask, expected_null_count] = + cudf::test::detail::make_null_mask(expected_validity, expected_validity + 5); + auto expected = cudf::make_lists_column(5, + offsets_column{0, 0, 1, 3, 4, 5}.release(), + expected_structs.release(), + expected_null_count, + std::move(expected_mask)); + + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(expected->view(), ret->get_column(0)); +} + TYPED_TEST(TypedScatterListsTest, EmptyListsOfFixedWidth) { using T = TypeParam; @@ -217,6 +293,37 @@ TEST_F(ScatterListsTest, ListsOfStrings) ret->get_column(0)); } +TEST_F(ScatterListsTest, SlicedInputListsOfStrings) +{ + auto src_list_column = + cudf::test::lists_column_wrapper{ + {{"zero"}, {"one", "one", "one"}, {"two", "two"}, {"three", "three", "three", "three"}}, + cudf::test::iterators::null_at(2)} + .release(); + auto src_sliced = cudf::slice(src_list_column->view(), {1, 4}).front(); + + auto target_list_column = + cudf::test::lists_column_wrapper{{"a", "a", "a", "a", "a"}, + {"b", "b", "b", "b", "b"}, + {"c", "c", "c", "c", "c"}, + {"d", "d", "d", "d", "d"}, + {"e", "e", "e", "e", "e"}}; + + auto scatter_map = cudf::test::fixed_width_column_wrapper{2, 0}; + + auto ret = cudf::scatter( + cudf::table_view({src_sliced}), scatter_map, cudf::table_view({target_list_column})); + + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + cudf::test::lists_column_wrapper{{{}, + {"b", "b", "b", "b", "b"}, + {"one", "one", "one"}, + {"d", "d", "d", "d", "d"}, + {"e", "e", "e", "e", "e"}}, + cudf::test::iterators::null_at(0)}, + ret->get_column(0)); +} + TEST_F(ScatterListsTest, ListsOfNullableStrings) { auto src_strings_column =