HiPipe  0.6.0
C++17 data pipeline with Python bindings.
unpack.hpp
1 /****************************************************************************
2  * hipipe library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Copyright (c) 2018, Iterait a.s.
5  * Author(s) Filip Matzner
6  *
7  * This file is distributed under the MIT License.
8  * See the accompanying file LICENSE.txt for the complete license agreement.
9  ****************************************************************************/
10 
11 #pragma once
12 
13 #include <hipipe/core/stream/stream_t.hpp>
14 #include <hipipe/core/stream/template_arguments.hpp>
15 #include <hipipe/core/utility/ndim.hpp>
16 #include <hipipe/core/utility/tuple.hpp>
17 
18 #include <range/v3/view/move.hpp>
19 #include <range/v3/view/transform.hpp>
20 
21 namespace hipipe::stream {
22 
23 namespace detail {
24 
25 
26  template<std::size_t Dim, bool OnlyOne, typename... FromColumns>
27  struct unpack_impl
28  {
29  template<typename Rng>
30  static auto unpack_columns(Rng&& rng)
31  {
32  return ranges::view::transform(std::forward<Rng>(rng), [](batch_t source)
33  -> std::tuple<typename FromColumns::data_type...> {
34  return {std::move(source.extract<FromColumns>())...};
35  });
36  }
37 
38  template<typename Rng>
39  static
40  std::tuple<std::vector<utility::ndim_type_t<typename FromColumns::data_type, Dim>>...>
41  impl(Rng&& range_of_batches)
42  {
43  static_assert(std::is_same_v<std::decay_t<ranges::range_value_type_t<Rng>>, batch_t>,
44  "hipipe::stream::unpack requires a range of batches as input.");
45  static_assert(((Dim <= utility::ndims<typename FromColumns::data_type>::value) && ...),
46  "hipipe::stream::unpack requires the requested dimension to be less or equal to the"
47  " dimension of all the unpacked columns.");
48  auto raw_range_of_tuples = unpack_columns(std::forward<Rng>(range_of_batches));
49  auto tuple_of_batches = utility::unzip(std::move(raw_range_of_tuples));
50  // flatten the values in each column upto the given dimension
51  return utility::tuple_transform(std::move(tuple_of_batches), [](auto&& batch_range) {
52  // make sure to convert the flat view to std::vector to avoid dangling ref
53  return ranges::view::move(utility::flat_view<Dim+1>(batch_range));
54  });
55  }
56  };
57 
58  // if only a single column is unpacked, do not return a tuple
59  template<std::size_t Dim, typename FromColumn>
60  struct unpack_impl<Dim, true, FromColumn>
61  {
62  template<typename Rng>
63  static
64  std::vector<utility::ndim_type_t<typename FromColumn::data_type, Dim>>
65  impl(Rng&& range_of_tuples)
66  {
67  return std::get<0>(
68  unpack_impl<Dim, false, FromColumn>::impl(std::forward<Rng>(range_of_tuples)));
69  }
70  };
71 
72 } // namespace detail
73 
74 
106 template<typename Rng, typename... FromColumns, int Dim = 1>
107 auto
108 // The return type is actually the following, but GCC won't handle it.
109 // utility::maybe_tuple<std::vector<utility::ndim_type_t<typename FromColumns::data_type, Dim>>...>
110 unpack(Rng&& rng, from_t<FromColumns...> f, dim_t<Dim> d = dim_t<1>{})
111 {
112  return detail::unpack_impl<Dim, (sizeof...(FromColumns)==1), FromColumns...>::impl(
113  std::forward<Rng>(rng));
114 }
115 
116 } // end namespace hipipe::stream
constexpr auto tuple_transform(Tuple &&tuple, Fun &&fun)
Transform each element of a tuple.
Definition: tuple.hpp:154
auto unpack(Rng &&rng, from_t< FromColumns... > f, dim_t< Dim > d=dim_t< 1 >{})
Unpack a stream into a tuple of ranges.
Definition: unpack.hpp:110
auto transform(from_t< FromColumns... > f, to_t< ToColumns... > t, Fun fun, dim_t< Dim > d=dim_t< 1 >{})
Transform a subset of hipipe columns to a different subset of hipipe columns.
Definition: transform.hpp:187
Definition: ndim.hpp:144
auto unzip(Rng range_of_tuples)
Unzips a range of tuples to a tuple of ranges.
Definition: tuple.hpp:257