Skip to content

Commit

Permalink
linestring_distance Header Only API Returns Past-the-End iterator (#…
Browse files Browse the repository at this point in the history
…670)

This PR updates `linestring_distance` to return past-the-end iterator to conform to other interfaces. Besides, this PR updates the assumption of `offset` arrays to be arrow compliant format (`N+1` instead of `N`).

closes #576

Authors:
  - Michael Wang (https://github.com/isVoid)

Approvers:
  - Mark Harris (https://github.com/harrism)
  - H. Thomson Comer (https://github.com/thomcom)

URL: #670
  • Loading branch information
isVoid authored Sep 19, 2022
1 parent 29307b0 commit 7dc27b6
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 102 deletions.
28 changes: 14 additions & 14 deletions cpp/include/cuspatial/experimental/detail/linestring_distance.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,10 @@ void __global__ pairwise_linestring_distance_kernel(OffsetIterator linestring1_o

if (p1_idx >= linestring1_num_points) { return; }

auto linestring_it =
thrust::upper_bound(thrust::seq, linestring1_offsets_begin, linestring1_offsets_end, p1_idx);
std::size_t const linestring_idx =
thrust::distance(linestring1_offsets_begin,
thrust::upper_bound(
thrust::seq, linestring1_offsets_begin, linestring1_offsets_end, p1_idx)) -
1;
thrust::distance(linestring1_offsets_begin, thrust::prev(linestring_it));

auto const ls1_end = endpoint_index_of_linestring(
linestring_idx, linestring1_offsets_begin, num_linestrings, linestring1_num_points);
Expand Down Expand Up @@ -138,15 +137,15 @@ void __global__ pairwise_linestring_distance_kernel(OffsetIterator linestring1_o
} // namespace detail

template <class Cart2dItA, class Cart2dItB, class OffsetIterator, class OutputIt>
void pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
OffsetIterator linestring1_offsets_last,
Cart2dItA linestring1_points_first,
Cart2dItA linestring1_points_last,
OffsetIterator linestring2_offsets_first,
Cart2dItB linestring2_points_first,
Cart2dItB linestring2_points_last,
OutputIt distances_first,
rmm::cuda_stream_view stream)
OutputIt pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
OffsetIterator linestring1_offsets_last,
Cart2dItA linestring1_points_first,
Cart2dItA linestring1_points_last,
OffsetIterator linestring2_offsets_first,
Cart2dItB linestring2_points_first,
Cart2dItB linestring2_points_last,
OutputIt distances_first,
rmm::cuda_stream_view stream)
{
using T = typename cuspatial::iterator_vec_base_type<Cart2dItA>;

Expand All @@ -161,7 +160,7 @@ void pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
"All input types must be cuspatial::vec_2d with the same value type");

auto const num_linestring_pairs =
thrust::distance(linestring1_offsets_first, linestring1_offsets_last);
thrust::distance(linestring1_offsets_first, linestring1_offsets_last) - 1;
auto const num_linestring1_points =
thrust::distance(linestring1_points_first, linestring1_points_last);
auto const num_linestring2_points =
Expand All @@ -187,6 +186,7 @@ void pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
distances_first);

CUSPATIAL_CUDA_TRY(cudaGetLastError());
return distances_first + num_linestring_pairs;
}

} // namespace cuspatial
19 changes: 10 additions & 9 deletions cpp/include/cuspatial/experimental/linestring_distance.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace cuspatial {
* @param linestring2_points_last end of range of the point of the second linestring of each pair
* @param distances_first beginning iterator to output
* @param stream The CUDA stream to use for device memory operations and kernel launches.
* @return Output iterator to one past the last element in the output range
*
* @pre all input iterators for coordinates must have `cuspatial::vec_2d` type.
* @pre all scalar types must be floating point types, and must be the same type for all input
Expand All @@ -59,15 +60,15 @@ namespace cuspatial {
* "LegacyRandomAccessIterator"
*/
template <class Cart2dItA, class Cart2dItB, class OffsetIterator, class OutputIt>
void pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
OffsetIterator linestring1_offsets_last,
Cart2dItA linestring1_points_first,
Cart2dItA linestring1_points_last,
OffsetIterator linestring2_offsets_first,
Cart2dItB linestring2_points_first,
Cart2dItB linestring2_points_last,
OutputIt distances_first,
rmm::cuda_stream_view stream = rmm::cuda_stream_default);
OutputIt pairwise_linestring_distance(OffsetIterator linestring1_offsets_first,
OffsetIterator linestring1_offsets_last,
Cart2dItA linestring1_points_first,
Cart2dItA linestring1_points_last,
OffsetIterator linestring2_offsets_first,
Cart2dItB linestring2_points_first,
Cart2dItB linestring2_points_last,
OutputIt distances_first,
rmm::cuda_stream_view stream = rmm::cuda_stream_default);

} // namespace cuspatial

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ namespace cuspatial {
* @param linestring_points_last end of the range of linestring points
* @param distances_first beginning of the output range of distances
* @param stream The CUDA stream to use for device memory operations and kernel launches.
* @return Output iterator to one past the last element in the output range
*
* @pre all input iterators for coordinates must have `cuspatial::vec_2d` type.
* @pre all scalar types must be floating point types, and must be the same type for all input
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/spatial/linestring_distance.cu
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct pairwise_linestring_distance_functor {
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr)
{
auto const num_string_pairs = static_cast<cudf::size_type>(linestring1_offsets.size());
auto const num_string_pairs = static_cast<cudf::size_type>(linestring1_offsets.size()) - 1;

auto distances = cudf::make_numeric_column(cudf::data_type{cudf::type_to_id<T>()},
num_string_pairs,
Expand Down Expand Up @@ -110,7 +110,7 @@ std::unique_ptr<cudf::column> pairwise_linestring_distance(
linestring1_points_x.type() == linestring2_points_x.type(),
"The types of linestring coordinates arrays mismatch.");

if (linestring1_offsets.size() == 0) { return cudf::empty_like(linestring1_points_x); }
if (linestring1_offsets.size() - 1 == 0) { return cudf::empty_like(linestring1_points_x); }

return cudf::type_dispatcher(linestring1_points_x.type(),
pairwise_linestring_distance_functor{},
Expand Down
78 changes: 46 additions & 32 deletions cpp/tests/experimental/spatial/linestring_distance_test.cu
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,22 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromSeparateArrayInputs)
CartVec({{0.0f, 0.0f}, {1.0f, 0.0f}, {2.0f, 0.0f}, {3.0f, 0.0f}, {4.0f, 0.0f}})};
auto b_cart2d = rmm::device_vector<vec_2d<T>>{
CartVec({{0.0f, 1.0f}, {1.0f, 1.0f}, {2.0f, 1.0f}, {3.0f, 1.0f}, {4.0f, 1.0f}})};
auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0}};
auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 5}};

auto distance = rmm::device_vector<T>{1};
auto expected = rmm::device_vector<T>{std::vector<T>{1.0}};

pairwise_linestring_distance(offset.begin(),
offset.end(),
a_cart2d.begin(),
a_cart2d.end(),
offset.begin(),
b_cart2d.begin(),
b_cart2d.end(),
distance.begin());
auto ret = pairwise_linestring_distance(offset.begin(),
offset.end(),
a_cart2d.begin(),
a_cart2d.end(),
offset.begin(),
b_cart2d.begin(),
b_cart2d.end(),
distance.begin());

test::expect_vector_equivalent(expected, distance);
EXPECT_EQ(offset.size() - 1, std::distance(distance.begin(), ret));
}

TYPED_TEST(PairwiseLinestringDistanceTest, FromSamePointArrayInput)
Expand All @@ -73,7 +74,8 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromSamePointArrayInput)

auto cart2ds = rmm::device_vector<vec_2d<T>>{
CartVec({{0.0f, 0.0f}, {1.0f, 0.0f}, {2.0f, 0.0f}, {3.0f, 0.0f}, {4.0f, 0.0f}})};
auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0}};
auto offset_a = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 3}};
auto offset_b = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 4}};

auto a_begin = cart2ds.begin();
auto a_end = cart2ds.begin() + 3;
Expand All @@ -83,10 +85,17 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromSamePointArrayInput)
auto distance = rmm::device_vector<T>{1};
auto expected = rmm::device_vector<T>{std::vector<T>{0.0}};

pairwise_linestring_distance(
offset.begin(), offset.end(), a_begin, a_end, offset.begin(), b_begin, b_end, distance.begin());
auto ret = pairwise_linestring_distance(offset_a.begin(),
offset_a.end(),
a_begin,
a_end,
offset_a.begin(),
b_begin,
b_end,
distance.begin());

test::expect_vector_equivalent(expected, distance);
EXPECT_EQ(offset_a.size() - 1, std::distance(distance.begin(), ret));
}

TYPED_TEST(PairwiseLinestringDistanceTest, FromTransformIterator)
Expand All @@ -106,15 +115,16 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromTransformIterator)
auto b_begin = make_vec_2d_iterator(b_cart2d_x.begin(), b_cart2d_y.begin());
auto b_end = b_begin + b_cart2d_x.size();

auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0}};
auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 5}};

auto distance = rmm::device_vector<T>{1};
auto expected = rmm::device_vector<T>{std::vector<T>{1.0}};

pairwise_linestring_distance(
auto ret = pairwise_linestring_distance(
offset.begin(), offset.end(), a_begin, a_end, offset.begin(), b_begin, b_end, distance.begin());

test::expect_vector_equivalent(expected, distance);
EXPECT_EQ(offset.size() - 1, std::distance(distance.begin(), ret));
}

TYPED_TEST(PairwiseLinestringDistanceTest, FromMixedIterator)
Expand All @@ -131,21 +141,23 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromMixedIterator)
auto b_begin = make_vec_2d_iterator(b_cart2d_x.begin(), b_cart2d_y.begin());
auto b_end = b_begin + b_cart2d_x.size();

auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0}};
auto offset_a = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 5}};
auto offset_b = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 5}};

auto distance = rmm::device_vector<T>{1};
auto expected = rmm::device_vector<T>{std::vector<T>{1.0}};

pairwise_linestring_distance(offset.begin(),
offset.end(),
a_cart2d.begin(),
a_cart2d.end(),
offset.begin(),
b_begin,
b_end,
distance.begin());
auto ret = pairwise_linestring_distance(offset_a.begin(),
offset_a.end(),
a_cart2d.begin(),
a_cart2d.end(),
offset_b.begin(),
b_begin,
b_end,
distance.begin());

test::expect_vector_equivalent(expected, distance);
EXPECT_EQ(offset_a.size() - 1, std::distance(distance.begin(), ret));
}

TYPED_TEST(PairwiseLinestringDistanceTest, FromLongInputs)
Expand All @@ -165,21 +177,23 @@ TYPED_TEST(PairwiseLinestringDistanceTest, FromLongInputs)
auto b_cart2d_begin = make_vec_2d_iterator(b_cart2d_x_begin, b_cart2d_y_begin);
auto b_cart2d_end = b_cart2d_begin + num_points;

auto offset = rmm::device_vector<int32_t>{std::vector<int32_t>{0, 100, 200, 300, 400}};
auto offset =
rmm::device_vector<int32_t>{std::vector<int32_t>{0, 100, 200, 300, 400, num_points}};

auto distance = rmm::device_vector<T>{5};
auto expected = rmm::device_vector<T>{std::vector<T>{42.0, 42.0, 42.0, 42.0, 42.0}};

pairwise_linestring_distance(offset.begin(),
offset.end(),
a_cart2d_begin,
a_cart2d_end,
offset.begin(),
b_cart2d_begin,
b_cart2d_end,
distance.begin());
auto ret = pairwise_linestring_distance(offset.begin(),
offset.end(),
a_cart2d_begin,
a_cart2d_end,
offset.begin(),
b_cart2d_begin,
b_cart2d_end,
distance.begin());

test::expect_vector_equivalent(expected, distance);
EXPECT_EQ(offset.size() - 1, std::distance(distance.begin(), ret));
}

} // namespace test
Expand Down
Loading

0 comments on commit 7dc27b6

Please sign in to comment.