Loading...
Searching...
No Matches
vector_factories.cuh
1/*
2 * Copyright (c) 2022-2024, 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
17#pragma once
18
19#include <cuspatial_test/test_util.cuh>
20
26#include <cuspatial/traits.hpp>
27
28#include <rmm/cuda_stream_view.hpp>
29#include <rmm/device_uvector.hpp>
30#include <rmm/device_vector.hpp>
31#include <rmm/resource_ref.hpp>
32
33#include <thrust/device_vector.h>
34#include <thrust/host_vector.h>
35
36#include <initializer_list>
37#include <numeric>
38#include <tuple>
39#include <vector>
40
41namespace cuspatial {
42namespace test {
43
44template <typename Range>
45auto make_device_vector(Range rng)
46{
47 using T = typename Range::value_type;
48 return rmm::device_vector<T>(rng.begin(), rng.end());
49}
50
51template <typename T>
52auto make_device_vector(std::initializer_list<T> inl)
53{
54 return rmm::device_vector<T>(inl.begin(), inl.end());
55}
56
57template <typename T>
58auto make_device_uvector(std::initializer_list<T> inl,
59 rmm::cuda_stream_view stream,
60 rmm::device_async_resource_ref mr)
61{
62 std::vector<T> hvec(inl.begin(), inl.end());
63 auto res = rmm::device_uvector<T>(inl.size(), stream, mr);
64 cudaMemcpyAsync(res.data(),
65 hvec.data(),
66 hvec.size() * sizeof(T),
67 cudaMemcpyKind::cudaMemcpyHostToDevice,
68 stream.value());
69 return res;
70}
71
80template <typename GeometryArray, typename PartArray, typename RingArray, typename CoordinateArray>
82 public:
83 using geometry_t = typename GeometryArray::value_type;
84 using part_t = typename PartArray::value_type;
85 using ring_t = typename RingArray::value_type;
86 using coord_t = typename CoordinateArray::value_type;
87
88 multipolygon_array(thrust::device_vector<geometry_t> geometry_offsets_array,
89 thrust::device_vector<part_t> part_offsets_array,
90 thrust::device_vector<ring_t> ring_offsets_array,
91 thrust::device_vector<coord_t> coordinates_array)
92 : _geometry_offsets_array(geometry_offsets_array),
93 _part_offsets_array(part_offsets_array),
94 _ring_offsets_array(ring_offsets_array),
95 _coordinates_array(coordinates_array)
96 {
97 }
98
99 multipolygon_array(rmm::device_vector<geometry_t>&& geometry_offsets_array,
100 rmm::device_vector<part_t>&& part_offsets_array,
101 rmm::device_vector<ring_t>&& ring_offsets_array,
102 rmm::device_vector<coord_t>&& coordinates_array)
103 : _geometry_offsets_array(std::move(geometry_offsets_array)),
104 _part_offsets_array(std::move(part_offsets_array)),
105 _ring_offsets_array(std::move(ring_offsets_array)),
106 _coordinates_array(std::move(coordinates_array))
107 {
108 }
109
110 multipolygon_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
111 rmm::device_uvector<part_t>&& part_offsets_array,
112 rmm::device_uvector<ring_t>&& ring_offsets_array,
113 rmm::device_uvector<coord_t>&& coordinates_array)
114 : _geometry_offsets_array(std::move(geometry_offsets_array)),
115 _part_offsets_array(std::move(part_offsets_array)),
116 _ring_offsets_array(std::move(ring_offsets_array)),
117 _coordinates_array(std::move(coordinates_array))
118 {
119 }
120
122 auto size() { return _geometry_offsets_array.size() - 1; }
123
125 auto range()
126 {
127 return multipolygon_range(_geometry_offsets_array.begin(),
128 _geometry_offsets_array.end(),
129 _part_offsets_array.begin(),
130 _part_offsets_array.end(),
131 _ring_offsets_array.begin(),
132 _ring_offsets_array.end(),
133 _coordinates_array.begin(),
134 _coordinates_array.end());
135 }
136
140 auto to_host() const
141 {
142 auto geometry_offsets = cuspatial::test::to_host<geometry_t>(_geometry_offsets_array);
143 auto part_offsets = cuspatial::test::to_host<part_t>(_part_offsets_array);
144 auto ring_offsets = cuspatial::test::to_host<ring_t>(_ring_offsets_array);
145 auto coordinate_offsets = cuspatial::test::to_host<coord_t>(_coordinates_array);
146
147 return std::tuple{geometry_offsets, part_offsets, ring_offsets, coordinate_offsets};
148 }
149
150 auto release()
151 {
152 return std::tuple{std::move(_geometry_offsets_array),
153 std::move(_part_offsets_array),
154 std::move(_ring_offsets_array),
155 std::move(_coordinates_array)};
156 }
157
161 friend std::ostream& operator<<(
162 std::ostream& os,
163 multipolygon_array<GeometryArray, PartArray, RingArray, CoordinateArray> const& arr)
164 {
165 auto [geometry_offsets, part_offsets, ring_offsets, coordinates] = arr.to_host();
166
167 auto print_vector = [&](auto const& vec) {
168 for (auto it = vec.begin(); it != vec.end(); it++) {
169 os << *it;
170 if (std::next(it) != vec.end()) { os << ", "; }
171 }
172 };
173
174 os << "Geometry Offsets:\n\t{";
175 print_vector(geometry_offsets);
176 os << "}\n";
177 os << "Part Offsets:\n\t{";
178 print_vector(part_offsets);
179 os << "}\n";
180 os << "Ring Offsets: \n\t{";
181 print_vector(ring_offsets);
182 os << "}\n";
183 os << "Coordinates: \n\t{";
184 print_vector(coordinates);
185 os << "}\n";
186 return os;
187 }
188
189 protected:
190 GeometryArray _geometry_offsets_array;
191 PartArray _part_offsets_array;
192 RingArray _ring_offsets_array;
193 CoordinateArray _coordinates_array;
194};
195
196template <typename IndexRange,
197 typename CoordRange,
198 typename IndexType = typename IndexRange::value_type>
199auto make_multipolygon_array(IndexRange geometry_inl,
200 IndexRange part_inl,
201 IndexRange ring_inl,
202 CoordRange coord_inl)
203{
204 using CoordType = typename CoordRange::value_type;
205 using DeviceIndexVector = thrust::device_vector<IndexType>;
206 using DeviceCoordVector = thrust::device_vector<CoordType>;
207
208 return multipolygon_array<DeviceIndexVector,
209 DeviceIndexVector,
210 DeviceIndexVector,
211 DeviceCoordVector>(make_device_vector(geometry_inl),
212 make_device_vector(part_inl),
213 make_device_vector(ring_inl),
214 make_device_vector(coord_inl));
215}
216
217template <typename T>
218auto make_multipolygon_array(std::initializer_list<std::size_t> geometry_inl,
219 std::initializer_list<std::size_t> part_inl,
220 std::initializer_list<std::size_t> ring_inl,
221 std::initializer_list<vec_2d<T>> coord_inl)
222{
223 return make_multipolygon_array(range(geometry_inl.begin(), geometry_inl.end()),
224 range(part_inl.begin(), part_inl.end()),
225 range(ring_inl.begin(), ring_inl.end()),
226 range(coord_inl.begin(), coord_inl.end()));
227}
228
229template <typename IndexType, typename CoordType>
230auto make_multipolygon_array(rmm::device_uvector<IndexType> geometry_inl,
231 rmm::device_uvector<IndexType> part_inl,
232 rmm::device_uvector<IndexType> ring_inl,
233 rmm::device_uvector<CoordType> coord_inl)
234{
235 return multipolygon_array<rmm::device_uvector<IndexType>,
236 rmm::device_uvector<IndexType>,
237 rmm::device_uvector<IndexType>,
238 rmm::device_uvector<CoordType>>(
239 std::move(geometry_inl), std::move(part_inl), std::move(ring_inl), std::move(coord_inl));
240}
241
249template <typename GeometryArray, typename PartArray, typename CoordinateArray>
251 public:
252 multilinestring_array(GeometryArray geometry_offsets_array,
253 PartArray part_offsets_array,
254 CoordinateArray coordinate_array)
255 : _geometry_offset_array(std::move(geometry_offsets_array)),
256 _part_offset_array(std::move(part_offsets_array)),
257 _coordinate_array(std::move(coordinate_array))
258 {
259 }
260
262 auto size() { return _geometry_offset_array.size() - 1; }
263
265 auto range()
266 {
267 return multilinestring_range(_geometry_offset_array.begin(),
268 _geometry_offset_array.end(),
269 _part_offset_array.begin(),
270 _part_offset_array.end(),
271 _coordinate_array.begin(),
272 _coordinate_array.end());
273 }
274
275 auto release()
276 {
277 return std::tuple{std::move(_geometry_offset_array),
278 std::move(_part_offset_array),
279 std::move(_coordinate_array)};
280 }
281
282 protected:
283 GeometryArray _geometry_offset_array;
284 PartArray _part_offset_array;
285 CoordinateArray _coordinate_array;
286};
287
296template <typename IndexType, typename T>
297auto make_multilinestring_array(rmm::device_uvector<IndexType>&& geometry_inl,
298 rmm::device_uvector<IndexType>&& part_inl,
299 rmm::device_uvector<vec_2d<T>>&& coord_inl)
300{
301 return multilinestring_array<rmm::device_uvector<IndexType>,
302 rmm::device_uvector<IndexType>,
303 rmm::device_uvector<vec_2d<T>>>(
304 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
305}
306
315template <typename IndexType, typename T>
316auto make_multilinestring_array(rmm::device_vector<IndexType>&& geometry_inl,
317 rmm::device_vector<IndexType>&& part_inl,
318 rmm::device_vector<vec_2d<T>>&& coord_inl)
319{
320 return multilinestring_array<rmm::device_vector<IndexType>,
321 rmm::device_vector<IndexType>,
322 rmm::device_vector<vec_2d<T>>>(
323 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
324}
325
335template <typename T>
336auto make_multilinestring_array(std::initializer_list<std::size_t> geometry_inl,
337 std::initializer_list<std::size_t> part_inl,
338 std::initializer_list<vec_2d<T>> coord_inl)
339{
340 return multilinestring_array(
341 rmm::device_vector<std::size_t>(
342 std::vector<std::size_t>(geometry_inl.begin(), geometry_inl.end())),
343 rmm::device_vector<std::size_t>(std::vector<unsigned int>(part_inl.begin(), part_inl.end())),
344 rmm::device_vector<vec_2d<T>>(std::vector<vec_2d<T>>(coord_inl.begin(), coord_inl.end())));
345}
346
353template <typename GeometryArray, typename CoordinateArray>
355 public:
356 using geometry_t = typename GeometryArray::value_type;
357 using coord_t = typename CoordinateArray::value_type;
358
359 multipoint_array(thrust::device_vector<geometry_t> geometry_offsets_array,
360 thrust::device_vector<coord_t> coordinate_array)
361 : _geometry_offsets(geometry_offsets_array), _coordinates(coordinate_array)
362 {
363 }
364
365 multipoint_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
366 rmm::device_uvector<coord_t>&& coordinate_array)
367 : _geometry_offsets(std::move(geometry_offsets_array)),
368 _coordinates(std::move(coordinate_array))
369 {
370 }
371
373 auto size() { return _geometry_offsets.size() - 1; }
374
376 auto range()
377 {
378 return multipoint_range{
379 _geometry_offsets.begin(), _geometry_offsets.end(), _coordinates.begin(), _coordinates.end()};
380 }
381
385 auto to_host() const
386 {
387 auto geometry_offsets = cuspatial::test::to_host<geometry_t>(_geometry_offsets);
388 auto coordinate_offsets = cuspatial::test::to_host<coord_t>(_coordinates);
389
390 return std::tuple{geometry_offsets, coordinate_offsets};
391 }
392
394 auto release() { return std::pair{std::move(_geometry_offsets), std::move(_coordinates)}; }
395
396 private:
397 GeometryArray _geometry_offsets;
398 CoordinateArray _coordinates;
399};
400
405template <typename GeometryRange, typename CoordRange>
406auto make_multipoint_array(GeometryRange geometry_inl, CoordRange coordinates_inl)
407{
408 using IndexType = typename GeometryRange::value_type;
409 using CoordType = typename CoordRange::value_type;
410 using DeviceIndexVector = thrust::device_vector<IndexType>;
411 using DeviceCoordVector = thrust::device_vector<CoordType>;
412
413 return multipoint_array<DeviceIndexVector, DeviceCoordVector>{
414 make_device_vector(geometry_inl), make_device_vector(coordinates_inl)};
415}
416
431template <typename T>
432auto make_multipoint_array(std::initializer_list<std::initializer_list<vec_2d<T>>> inl)
433{
434 std::vector<std::size_t> offsets{0};
435 std::transform(inl.begin(), inl.end(), std::back_inserter(offsets), [](auto multipoint) {
436 return multipoint.size();
437 });
438 std::inclusive_scan(offsets.begin(), offsets.end(), offsets.begin());
439
440 std::vector<vec_2d<T>> coordinates = std::accumulate(
441 inl.begin(), inl.end(), std::vector<vec_2d<T>>{}, [](std::vector<vec_2d<T>>& init, auto cur) {
442 init.insert(init.end(), cur.begin(), cur.end());
443 return init;
444 });
445
446 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
447 rmm::device_vector<std::size_t>(offsets), rmm::device_vector<vec_2d<T>>(coordinates)};
448}
449
454template <typename IndexType, typename T>
455auto make_multipoint_array(rmm::device_uvector<IndexType> geometry_offsets,
456 rmm::device_uvector<vec_2d<T>> coords)
457{
458 return multipoint_array<rmm::device_uvector<std::size_t>, rmm::device_uvector<vec_2d<T>>>{
459 std::move(geometry_offsets), std::move(coords)};
460}
461
466template <typename IndexType, typename T>
467auto make_multipoint_array(rmm::device_vector<IndexType> geometry_offsets,
468 rmm::device_vector<vec_2d<T>> coords)
469{
470 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
471 std::move(geometry_offsets), std::move(coords)};
472}
473
474} // namespace test
475} // namespace cuspatial
Non-owning range-based interface to multilinestring data.
Non-owning range-based interface to multipoint data.
Non-owning range-based interface to multipolygon data.
Owning object of a multilinestring array following geoarrow layout.
auto size()
Return the number of multilinestrings.
auto range()
Return range object of the multilinestring array.
Owning object of a multipoint array following geoarrow format.
auto size()
Return the number of multipoints.
auto to_host() const
Copy the offset arrays to host.
auto range()
Return range object of the multipoint array.
Owning object of a multipolygon array following geoarrow layout.
auto range()
Return range object of the multipolygon array.
auto to_host() const
Copy the offset arrays to host.
friend std::ostream & operator<<(std::ostream &os, multipolygon_array< GeometryArray, PartArray, RingArray, CoordinateArray > const &arr)
Output stream operator for multipolygon_array for human-readable formatting.
auto size()
Return the number of multipolygons.