Loading...
Searching...
No Matches
vector_factories.cuh
1/*
2 * Copyright (c) 2022-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
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
32#include <thrust/device_vector.h>
33#include <thrust/host_vector.h>
34
35#include <initializer_list>
36#include <numeric>
37#include <tuple>
38#include <vector>
39
40namespace cuspatial {
41namespace test {
42
43template <typename Range>
44auto make_device_vector(Range rng)
45{
46 using T = typename Range::value_type;
47 return rmm::device_vector<T>(rng.begin(), rng.end());
48}
49
50template <typename T>
51auto make_device_vector(std::initializer_list<T> inl)
52{
53 return rmm::device_vector<T>(inl.begin(), inl.end());
54}
55
56template <typename T>
57auto make_device_uvector(std::initializer_list<T> inl,
58 rmm::cuda_stream_view stream,
59 rmm::mr::device_memory_resource* mr)
60{
61 std::vector<T> hvec(inl.begin(), inl.end());
62 auto res = rmm::device_uvector<T>(inl.size(), stream, mr);
63 cudaMemcpyAsync(res.data(),
64 hvec.data(),
65 hvec.size() * sizeof(T),
66 cudaMemcpyKind::cudaMemcpyHostToDevice,
67 stream.value());
68 return res;
69}
70
79template <typename GeometryArray, typename PartArray, typename RingArray, typename CoordinateArray>
81 public:
82 using geometry_t = typename GeometryArray::value_type;
83 using part_t = typename PartArray::value_type;
84 using ring_t = typename RingArray::value_type;
85 using coord_t = typename CoordinateArray::value_type;
86
87 multipolygon_array(thrust::device_vector<geometry_t> geometry_offsets_array,
88 thrust::device_vector<part_t> part_offsets_array,
89 thrust::device_vector<ring_t> ring_offsets_array,
90 thrust::device_vector<coord_t> coordinates_array)
91 : _geometry_offsets_array(geometry_offsets_array),
92 _part_offsets_array(part_offsets_array),
93 _ring_offsets_array(ring_offsets_array),
94 _coordinates_array(coordinates_array)
95 {
96 }
97
98 multipolygon_array(rmm::device_vector<geometry_t>&& geometry_offsets_array,
99 rmm::device_vector<part_t>&& part_offsets_array,
100 rmm::device_vector<ring_t>&& ring_offsets_array,
101 rmm::device_vector<coord_t>&& coordinates_array)
102 : _geometry_offsets_array(std::move(geometry_offsets_array)),
103 _part_offsets_array(std::move(part_offsets_array)),
104 _ring_offsets_array(std::move(ring_offsets_array)),
105 _coordinates_array(std::move(coordinates_array))
106 {
107 }
108
109 multipolygon_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
110 rmm::device_uvector<part_t>&& part_offsets_array,
111 rmm::device_uvector<ring_t>&& ring_offsets_array,
112 rmm::device_uvector<coord_t>&& coordinates_array)
113 : _geometry_offsets_array(std::move(geometry_offsets_array)),
114 _part_offsets_array(std::move(part_offsets_array)),
115 _ring_offsets_array(std::move(ring_offsets_array)),
116 _coordinates_array(std::move(coordinates_array))
117 {
118 }
119
121 auto size() { return _geometry_offsets_array.size() - 1; }
122
124 auto range()
125 {
126 return multipolygon_range(_geometry_offsets_array.begin(),
127 _geometry_offsets_array.end(),
128 _part_offsets_array.begin(),
129 _part_offsets_array.end(),
130 _ring_offsets_array.begin(),
131 _ring_offsets_array.end(),
132 _coordinates_array.begin(),
133 _coordinates_array.end());
134 }
135
139 auto to_host() const
140 {
141 auto geometry_offsets = cuspatial::test::to_host<geometry_t>(_geometry_offsets_array);
142 auto part_offsets = cuspatial::test::to_host<part_t>(_part_offsets_array);
143 auto ring_offsets = cuspatial::test::to_host<ring_t>(_ring_offsets_array);
144 auto coordinate_offsets = cuspatial::test::to_host<coord_t>(_coordinates_array);
145
146 return std::tuple{geometry_offsets, part_offsets, ring_offsets, coordinate_offsets};
147 }
148
149 auto release()
150 {
151 return std::tuple{std::move(_geometry_offsets_array),
152 std::move(_part_offsets_array),
153 std::move(_ring_offsets_array),
154 std::move(_coordinates_array)};
155 }
156
160 friend std::ostream& operator<<(
161 std::ostream& os,
162 multipolygon_array<GeometryArray, PartArray, RingArray, CoordinateArray> const& arr)
163 {
164 auto [geometry_offsets, part_offsets, ring_offsets, coordinates] = arr.to_host();
165
166 return os << "Geometry Offsets:\n\t{" << geometry_offsets << "}\n"
167 << "Part Offsets:\n\t{" << part_offsets << "}\n"
168 << "Ring Offsets: \n\t{" << ring_offsets << "}\n"
169 << "Coordinates: \n\t{" << coordinates << "}\n";
170 }
171
172 protected:
173 GeometryArray _geometry_offsets_array;
174 PartArray _part_offsets_array;
175 RingArray _ring_offsets_array;
176 CoordinateArray _coordinates_array;
177};
178
179template <typename IndexRange,
180 typename CoordRange,
181 typename IndexType = typename IndexRange::value_type>
182auto make_multipolygon_array(IndexRange geometry_inl,
183 IndexRange part_inl,
184 IndexRange ring_inl,
185 CoordRange coord_inl)
186{
187 using CoordType = typename CoordRange::value_type;
188 using DeviceIndexVector = thrust::device_vector<IndexType>;
189 using DeviceCoordVector = thrust::device_vector<CoordType>;
190
191 return multipolygon_array<DeviceIndexVector,
192 DeviceIndexVector,
193 DeviceIndexVector,
194 DeviceCoordVector>(make_device_vector(geometry_inl),
195 make_device_vector(part_inl),
196 make_device_vector(ring_inl),
197 make_device_vector(coord_inl));
198}
199
200template <typename T>
201auto make_multipolygon_array(std::initializer_list<std::size_t> geometry_inl,
202 std::initializer_list<std::size_t> part_inl,
203 std::initializer_list<std::size_t> ring_inl,
204 std::initializer_list<vec_2d<T>> coord_inl)
205{
206 return make_multipolygon_array(range(geometry_inl.begin(), geometry_inl.end()),
207 range(part_inl.begin(), part_inl.end()),
208 range(ring_inl.begin(), ring_inl.end()),
209 range(coord_inl.begin(), coord_inl.end()));
210}
211
212template <typename IndexType, typename CoordType>
213auto make_multipolygon_array(rmm::device_uvector<IndexType> geometry_inl,
214 rmm::device_uvector<IndexType> part_inl,
215 rmm::device_uvector<IndexType> ring_inl,
216 rmm::device_uvector<CoordType> coord_inl)
217{
218 return multipolygon_array<rmm::device_uvector<IndexType>,
219 rmm::device_uvector<IndexType>,
220 rmm::device_uvector<IndexType>,
221 rmm::device_uvector<CoordType>>(
222 std::move(geometry_inl), std::move(part_inl), std::move(ring_inl), std::move(coord_inl));
223}
224
232template <typename GeometryArray, typename PartArray, typename CoordinateArray>
234 public:
235 multilinestring_array(GeometryArray geometry_offsets_array,
236 PartArray part_offsets_array,
237 CoordinateArray coordinate_array)
238 : _geometry_offset_array(std::move(geometry_offsets_array)),
239 _part_offset_array(std::move(part_offsets_array)),
240 _coordinate_array(std::move(coordinate_array))
241 {
242 }
243
245 auto size() { return _geometry_offset_array.size() - 1; }
246
248 auto range()
249 {
250 return multilinestring_range(_geometry_offset_array.begin(),
251 _geometry_offset_array.end(),
252 _part_offset_array.begin(),
253 _part_offset_array.end(),
254 _coordinate_array.begin(),
255 _coordinate_array.end());
256 }
257
258 auto release()
259 {
260 return std::tuple{std::move(_geometry_offset_array),
261 std::move(_part_offset_array),
262 std::move(_coordinate_array)};
263 }
264
265 protected:
266 GeometryArray _geometry_offset_array;
267 PartArray _part_offset_array;
268 CoordinateArray _coordinate_array;
269};
270
279template <typename IndexType, typename T>
280auto make_multilinestring_array(rmm::device_uvector<IndexType>&& geometry_inl,
281 rmm::device_uvector<IndexType>&& part_inl,
282 rmm::device_uvector<vec_2d<T>>&& coord_inl)
283{
284 return multilinestring_array<rmm::device_uvector<IndexType>,
285 rmm::device_uvector<IndexType>,
286 rmm::device_uvector<vec_2d<T>>>(
287 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
288}
289
298template <typename IndexType, typename T>
299auto make_multilinestring_array(rmm::device_vector<IndexType>&& geometry_inl,
300 rmm::device_vector<IndexType>&& part_inl,
301 rmm::device_vector<vec_2d<T>>&& coord_inl)
302{
303 return multilinestring_array<rmm::device_vector<IndexType>,
304 rmm::device_vector<IndexType>,
305 rmm::device_vector<vec_2d<T>>>(
306 std::move(geometry_inl), std::move(part_inl), std::move(coord_inl));
307}
308
318template <typename T>
319auto make_multilinestring_array(std::initializer_list<std::size_t> geometry_inl,
320 std::initializer_list<std::size_t> part_inl,
321 std::initializer_list<vec_2d<T>> coord_inl)
322{
323 return multilinestring_array(
324 rmm::device_vector<std::size_t>(
325 std::vector<std::size_t>(geometry_inl.begin(), geometry_inl.end())),
326 rmm::device_vector<std::size_t>(std::vector<unsigned int>(part_inl.begin(), part_inl.end())),
327 rmm::device_vector<vec_2d<T>>(std::vector<vec_2d<T>>(coord_inl.begin(), coord_inl.end())));
328}
329
336template <typename GeometryArray, typename CoordinateArray>
338 public:
339 using geometry_t = typename GeometryArray::value_type;
340 using coord_t = typename CoordinateArray::value_type;
341
342 multipoint_array(thrust::device_vector<geometry_t> geometry_offsets_array,
343 thrust::device_vector<coord_t> coordinate_array)
344 : _geometry_offsets(geometry_offsets_array), _coordinates(coordinate_array)
345 {
346 }
347
348 multipoint_array(rmm::device_uvector<geometry_t>&& geometry_offsets_array,
349 rmm::device_uvector<coord_t>&& coordinate_array)
350 : _geometry_offsets(std::move(geometry_offsets_array)),
351 _coordinates(std::move(coordinate_array))
352 {
353 }
354
356 auto size() { return _geometry_offsets.size() - 1; }
357
359 auto range()
360 {
361 return multipoint_range{
362 _geometry_offsets.begin(), _geometry_offsets.end(), _coordinates.begin(), _coordinates.end()};
363 }
364
366 auto release() { return std::pair{std::move(_geometry_offsets), std::move(_coordinates)}; }
367
368 private:
369 GeometryArray _geometry_offsets;
370 CoordinateArray _coordinates;
371};
372
377template <typename GeometryRange, typename CoordRange>
378auto make_multipoint_array(GeometryRange geometry_inl, CoordRange coordinates_inl)
379{
380 using IndexType = typename GeometryRange::value_type;
381 using CoordType = typename CoordRange::value_type;
382 using DeviceIndexVector = thrust::device_vector<IndexType>;
383 using DeviceCoordVector = thrust::device_vector<CoordType>;
384
385 return multipoint_array<DeviceIndexVector, DeviceCoordVector>{
386 make_device_vector(geometry_inl), make_device_vector(coordinates_inl)};
387}
388
403template <typename T>
404auto make_multipoint_array(std::initializer_list<std::initializer_list<vec_2d<T>>> inl)
405{
406 std::vector<std::size_t> offsets{0};
407 std::transform(inl.begin(), inl.end(), std::back_inserter(offsets), [](auto multipoint) {
408 return multipoint.size();
409 });
410 std::inclusive_scan(offsets.begin(), offsets.end(), offsets.begin());
411
412 std::vector<vec_2d<T>> coordinates = std::accumulate(
413 inl.begin(), inl.end(), std::vector<vec_2d<T>>{}, [](std::vector<vec_2d<T>>& init, auto cur) {
414 init.insert(init.end(), cur.begin(), cur.end());
415 return init;
416 });
417
418 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
419 rmm::device_vector<std::size_t>(offsets), rmm::device_vector<vec_2d<T>>(coordinates)};
420}
421
426template <typename IndexType, typename T>
427auto make_multipoint_array(rmm::device_uvector<IndexType> geometry_offsets,
428 rmm::device_uvector<vec_2d<T>> coords)
429{
430 return multipoint_array<rmm::device_uvector<std::size_t>, rmm::device_uvector<vec_2d<T>>>{
431 std::move(geometry_offsets), std::move(coords)};
432}
433
438template <typename IndexType, typename T>
439auto make_multipoint_array(rmm::device_vector<IndexType> geometry_offsets,
440 rmm::device_vector<vec_2d<T>> coords)
441{
442 return multipoint_array<rmm::device_vector<std::size_t>, rmm::device_vector<vec_2d<T>>>{
443 std::move(geometry_offsets), std::move(coords)};
444}
445
446} // namespace test
447} // 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 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.