GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/eigenpy/std-array.hpp Lines: 47 49 95.9 %
Date: 2024-05-13 21:27:44 Branches: 32 65 49.2 %

Line Branch Exec Source
1
///
2
/// Copyright (c) 2023-2024 CNRS INRIA
3
///
4
5
#ifndef __eigenpy_utils_std_array_hpp__
6
#define __eigenpy_utils_std_array_hpp__
7
8
#include <boost/python/suite/indexing/indexing_suite.hpp>
9
#include "eigenpy/std-vector.hpp"
10
11
#include <array>
12
13
namespace eigenpy {
14
15
template <typename Container, bool NoProxy, class SliceAllocator,
16
          class DerivedPolicies>
17
class array_indexing_suite;
18
namespace details {
19
20
template <typename Container, bool NoProxy, class SliceAllocator>
21
class final_array_derived_policies
22
    : public array_indexing_suite<
23
          Container, NoProxy, SliceAllocator,
24
          final_array_derived_policies<Container, NoProxy, SliceAllocator> > {};
25
}  // namespace details
26
27
template <typename Container, bool NoProxy = false,
28
          class SliceAllocator = std::allocator<typename Container::value_type>,
29
          class DerivedPolicies = details::final_array_derived_policies<
30
              Container, NoProxy, SliceAllocator> >
31
class array_indexing_suite
32
    : public bp::vector_indexing_suite<Container, NoProxy, DerivedPolicies> {
33
 public:
34
  typedef typename Container::value_type data_type;
35
  typedef typename Container::value_type key_type;
36
  typedef typename Container::size_type index_type;
37
  typedef typename Container::size_type size_type;
38
  typedef typename Container::difference_type difference_type;
39
  typedef std::vector<data_type, SliceAllocator> slice_vector_type;
40
  static constexpr std::size_t Size = std::tuple_size<Container>{};
41
42
  template <class Class>
43
12
  static void extension_def(Class &) {}
44
45
  // throws exception
46
2
  static void delete_item(Container &, index_type) {
47
2
    PyErr_SetString(PyExc_NotImplementedError,
48
                    "Cannot delete item from std::array type.");
49
2
    bp::throw_error_already_set();
50
  }
51
52
  // throws exception
53
4
  static void delete_slice(Container &, index_type, index_type) {
54
4
    PyErr_SetString(PyExc_NotImplementedError,
55
                    "Cannot delete slice from std::array type.");
56
4
    bp::throw_error_already_set();
57
  }
58
59
2
  static void set_slice(Container &container, index_type from, index_type to,
60
                        data_type const &v) {
61
2
    if (from >= to) {
62
      PyErr_SetString(PyExc_NotImplementedError,
63
                      "Setting this slice would insert into an std::array, "
64
                      "which is not supported.");
65
      bp::throw_error_already_set();
66
    } else {
67
2
      std::fill(container.begin() + from, container.begin() + to, v);
68
    }
69
  }
70
71
  template <class Iter>
72
12
  static void set_slice(Container &container, index_type from, index_type to,
73
                        Iter first, Iter last) {
74
12
    if (from >= to) {
75
6
      PyErr_SetString(PyExc_NotImplementedError,
76
                      "Setting this slice would insert into an std::array, "
77
                      "which is not supported.");
78
6
      bp::throw_error_already_set();
79
    } else {
80
6
      if (long(to - from) == std::distance(first, last)) {
81
2
        std::copy(first, last, container.begin() + from);
82
      } else {
83
4
        PyErr_SetString(PyExc_NotImplementedError,
84
                        "Size of std::array slice and size of right-hand side "
85
                        "iterator are incompatible.");
86
4
        bp::throw_error_already_set();
87
      }
88
    }
89
  }
90
91
6
  static bp::object get_slice(Container &container, index_type from,
92
                              index_type to) {
93

6
    if (from > to) return bp::object(slice_vector_type());
94
12
    slice_vector_type out;
95
22
    for (size_t i = from; i < to; i++) {
96
16
      out.push_back(container[i]);
97
    }
98
6
    return bp::object(std::move(out));
99
  }
100
};
101
102
/// \brief Expose an std::array (a C++11 fixed-size array) from a given type
103
/// \tparam array_type std::array type to expose
104
/// \tparam NoProxy When set to false, the elements will be copied when
105
/// returned to Python.
106
/// \tparam SliceAllocator Allocator type to use for slices of std::array type
107
/// accessed using e.g. __getitem__[0:4] in Python. These slices are returned as
108
/// std::vector (dynamic size).
109
template <typename array_type, bool NoProxy = false,
110
          class SliceAllocator =
111
              std::allocator<typename array_type::value_type> >
112
struct StdArrayPythonVisitor {
113
  typedef typename array_type::value_type value_type;
114
115
4
  static ::boost::python::list tolist(array_type &self, const bool deep_copy) {
116
4
    return details::build_list<array_type, NoProxy>::run(self, deep_copy);
117
  }
118
119
2
  static void expose(const std::string &class_name,
120
                     const std::string &doc_string = "") {
121
2
    expose(class_name, doc_string, EmptyPythonVisitor());
122
2
  }
123
124
  template <typename DerivedVisitor>
125
8
  static void expose(const std::string &class_name,
126
                     const bp::def_visitor<DerivedVisitor> &visitor) {
127

8
    expose(class_name, "", visitor);
128
8
  }
129
130
  template <typename DerivedVisitor>
131
12
  static void expose(const std::string &class_name,
132
                     const std::string &doc_string,
133
                     const bp::def_visitor<DerivedVisitor> &visitor) {
134
12
    if (!register_symbolic_link_to_registered_type<array_type>()) {
135
12
      bp::class_<array_type> cl(class_name.c_str(), doc_string.c_str());
136

12
      cl.def(bp::init<const array_type &>(bp::args("self", "other"),
137
                                          "Copy constructor"));
138
139
      array_indexing_suite<array_type, NoProxy, SliceAllocator> indexing_suite;
140
24
      cl.def(indexing_suite)
141
12
          .def(visitor)
142

12
          .def("tolist", tolist,
143

24
               (bp::arg("self"), bp::arg("deep_copy") = false),
144
               "Returns the std::array as a Python list.");
145
    }
146
12
  }
147
};
148
149
/// Exposes std::array<MatrixType, Size>
150
template <typename MatrixType, std::size_t Size>
151
8
void exposeStdArrayEigenSpecificType(const char *name) {
152
8
  std::ostringstream oss;
153
8
  oss << "StdArr";
154

8
  oss << Size << "_" << name;
155
  typedef std::array<MatrixType, Size> array_type;
156
  StdArrayPythonVisitor<array_type, false,
157
                        Eigen::aligned_allocator<MatrixType> >::
158

8
      expose(oss.str(),
159
             details::overload_base_get_item_for_std_vector<array_type>());
160
8
}
161
162
}  // namespace eigenpy
163
164
#endif  // ifndef __eigenpy_utils_std_array_hpp__