Resolve "SYCL + DPCPP cmake config fails in gmxManageFFTLibraries.cmake"
[alexxy/gromacs.git] / python_packaging / src / external / pybind / include / pybind11 / stl_bind.h
1 /*
2     pybind11/std_bind.h: Binding generators for STL data types
3
4     Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
5
6     All rights reserved. Use of this source code is governed by a
7     BSD-style license that can be found in the LICENSE file.
8 */
9
10 #pragma once
11
12 #include "detail/common.h"
13 #include "operators.h"
14
15 #include <algorithm>
16 #include <sstream>
17
18 NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
19 NAMESPACE_BEGIN(detail)
20
21 /* SFINAE helper class used by 'is_comparable */
22 template <typename T>  struct container_traits {
23     template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*);
24     template <typename T2> static std::false_type test_comparable(...);
25     template <typename T2> static std::true_type test_value(typename T2::value_type *);
26     template <typename T2> static std::false_type test_value(...);
27     template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
28     template <typename T2> static std::false_type test_pair(...);
29
30     static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
31     static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
32     static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
33     static constexpr const bool is_element = !is_pair && !is_vector;
34 };
35
36 /* Default: is_comparable -> std::false_type */
37 template <typename T, typename SFINAE = void>
38 struct is_comparable : std::false_type { };
39
40 /* For non-map data structures, check whether operator== can be instantiated */
41 template <typename T>
42 struct is_comparable<
43     T, enable_if_t<container_traits<T>::is_element &&
44                    container_traits<T>::is_comparable>>
45     : std::true_type { };
46
47 /* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
48 template <typename T>
49 struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>> {
50     static constexpr const bool value =
51         is_comparable<typename T::value_type>::value;
52 };
53
54 /* For pairs, recursively check the two data types */
55 template <typename T>
56 struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> {
57     static constexpr const bool value =
58         is_comparable<typename T::first_type>::value &&
59         is_comparable<typename T::second_type>::value;
60 };
61
62 /* Fallback functions */
63 template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args &...) { }
64 template <typename, typename, typename... Args> void vector_if_equal_operator(const Args &...) { }
65 template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args &...) { }
66 template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { }
67
68 template<typename Vector, typename Class_>
69 void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
70     cl.def(init<const Vector &>(), "Copy constructor");
71 }
72
73 template<typename Vector, typename Class_>
74 void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) {
75     using T = typename Vector::value_type;
76
77     cl.def(self == self);
78     cl.def(self != self);
79
80     cl.def("count",
81         [](const Vector &v, const T &x) {
82             return std::count(v.begin(), v.end(), x);
83         },
84         arg("x"),
85         "Return the number of times ``x`` appears in the list"
86     );
87
88     cl.def("remove", [](Vector &v, const T &x) {
89             auto p = std::find(v.begin(), v.end(), x);
90             if (p != v.end())
91                 v.erase(p);
92             else
93                 throw value_error();
94         },
95         arg("x"),
96         "Remove the first item from the list whose value is x. "
97         "It is an error if there is no such item."
98     );
99
100     cl.def("__contains__",
101         [](const Vector &v, const T &x) {
102             return std::find(v.begin(), v.end(), x) != v.end();
103         },
104         arg("x"),
105         "Return true the container contains ``x``"
106     );
107 }
108
109 // Vector modifiers -- requires a copyable vector_type:
110 // (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems
111 // silly to allow deletion but not insertion, so include them here too.)
112 template <typename Vector, typename Class_>
113 void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
114     using T = typename Vector::value_type;
115     using SizeType = typename Vector::size_type;
116     using DiffType = typename Vector::difference_type;
117
118     auto wrap_i = [](DiffType i, SizeType n) {
119         if (i < 0)
120             i += n;
121         if (i < 0 || (SizeType)i >= n)
122             throw index_error();
123         return i;
124     };
125
126     cl.def("append",
127            [](Vector &v, const T &value) { v.push_back(value); },
128            arg("x"),
129            "Add an item to the end of the list");
130
131     cl.def(init([](iterable it) {
132         auto v = std::unique_ptr<Vector>(new Vector());
133         v->reserve(len_hint(it));
134         for (handle h : it)
135            v->push_back(h.cast<T>());
136         return v.release();
137     }));
138
139     cl.def("clear",
140         [](Vector &v) {
141             v.clear();
142         },
143         "Clear the contents"
144     );
145
146     cl.def("extend",
147        [](Vector &v, const Vector &src) {
148            v.insert(v.end(), src.begin(), src.end());
149        },
150        arg("L"),
151        "Extend the list by appending all the items in the given list"
152     );
153
154     cl.def("extend",
155        [](Vector &v, iterable it) {
156            const size_t old_size = v.size();
157            v.reserve(old_size + len_hint(it));
158            try {
159                for (handle h : it) {
160                    v.push_back(h.cast<T>());
161                }
162            } catch (const cast_error &) {
163                v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size), v.end());
164                try {
165                    v.shrink_to_fit();
166                } catch (const std::exception &) {
167                    // Do nothing
168                }
169                throw;
170            }
171        },
172        arg("L"),
173        "Extend the list by appending all the items in the given list"
174     );
175
176     cl.def("insert",
177         [](Vector &v, DiffType i, const T &x) {
178             // Can't use wrap_i; i == v.size() is OK
179             if (i < 0)
180                 i += v.size();
181             if (i < 0 || (SizeType)i > v.size())
182                 throw index_error();
183             v.insert(v.begin() + i, x);
184         },
185         arg("i") , arg("x"),
186         "Insert an item at a given position."
187     );
188
189     cl.def("pop",
190         [](Vector &v) {
191             if (v.empty())
192                 throw index_error();
193             T t = v.back();
194             v.pop_back();
195             return t;
196         },
197         "Remove and return the last item"
198     );
199
200     cl.def("pop",
201         [wrap_i](Vector &v, DiffType i) {
202             i = wrap_i(i, v.size());
203             T t = v[(SizeType) i];
204             v.erase(v.begin() + i);
205             return t;
206         },
207         arg("i"),
208         "Remove and return the item at index ``i``"
209     );
210
211     cl.def("__setitem__",
212         [wrap_i](Vector &v, DiffType i, const T &t) {
213             i = wrap_i(i, v.size());
214             v[(SizeType)i] = t;
215         }
216     );
217
218     /// Slicing protocol
219     cl.def("__getitem__",
220         [](const Vector &v, slice slice) -> Vector * {
221             size_t start, stop, step, slicelength;
222
223             if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
224                 throw error_already_set();
225
226             Vector *seq = new Vector();
227             seq->reserve((size_t) slicelength);
228
229             for (size_t i=0; i<slicelength; ++i) {
230                 seq->push_back(v[start]);
231                 start += step;
232             }
233             return seq;
234         },
235         arg("s"),
236         "Retrieve list elements using a slice object"
237     );
238
239     cl.def("__setitem__",
240         [](Vector &v, slice slice,  const Vector &value) {
241             size_t start, stop, step, slicelength;
242             if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
243                 throw error_already_set();
244
245             if (slicelength != value.size())
246                 throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
247
248             for (size_t i=0; i<slicelength; ++i) {
249                 v[start] = value[i];
250                 start += step;
251             }
252         },
253         "Assign list elements using a slice object"
254     );
255
256     cl.def("__delitem__",
257         [wrap_i](Vector &v, DiffType i) {
258             i = wrap_i(i, v.size());
259             v.erase(v.begin() + i);
260         },
261         "Delete the list elements at index ``i``"
262     );
263
264     cl.def("__delitem__",
265         [](Vector &v, slice slice) {
266             size_t start, stop, step, slicelength;
267
268             if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
269                 throw error_already_set();
270
271             if (step == 1 && false) {
272                 v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
273             } else {
274                 for (size_t i = 0; i < slicelength; ++i) {
275                     v.erase(v.begin() + DiffType(start));
276                     start += step - 1;
277                 }
278             }
279         },
280         "Delete list elements using a slice object"
281     );
282
283 }
284
285 // If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>),
286 // we have to access by copying; otherwise we return by reference.
287 template <typename Vector> using vector_needs_copy = negation<
288     std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]), typename Vector::value_type &>>;
289
290 // The usual case: access and iterate by reference
291 template <typename Vector, typename Class_>
292 void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) {
293     using T = typename Vector::value_type;
294     using SizeType = typename Vector::size_type;
295     using DiffType = typename Vector::difference_type;
296     using ItType   = typename Vector::iterator;
297
298     auto wrap_i = [](DiffType i, SizeType n) {
299         if (i < 0)
300             i += n;
301         if (i < 0 || (SizeType)i >= n)
302             throw index_error();
303         return i;
304     };
305
306     cl.def("__getitem__",
307         [wrap_i](Vector &v, DiffType i) -> T & {
308             i = wrap_i(i, v.size());
309             return v[(SizeType)i];
310         },
311         return_value_policy::reference_internal // ref + keepalive
312     );
313
314     cl.def("__iter__",
315            [](Vector &v) {
316                return make_iterator<
317                    return_value_policy::reference_internal, ItType, ItType, T&>(
318                    v.begin(), v.end());
319            },
320            keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
321     );
322 }
323
324 // The case for special objects, like std::vector<bool>, that have to be returned-by-copy:
325 template <typename Vector, typename Class_>
326 void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) {
327     using T = typename Vector::value_type;
328     using SizeType = typename Vector::size_type;
329     using DiffType = typename Vector::difference_type;
330     using ItType   = typename Vector::iterator;
331     cl.def("__getitem__",
332         [](const Vector &v, DiffType i) -> T {
333             if (i < 0 && (i += v.size()) < 0)
334                 throw index_error();
335             if ((SizeType)i >= v.size())
336                 throw index_error();
337             return v[(SizeType)i];
338         }
339     );
340
341     cl.def("__iter__",
342            [](Vector &v) {
343                return make_iterator<
344                    return_value_policy::copy, ItType, ItType, T>(
345                    v.begin(), v.end());
346            },
347            keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
348     );
349 }
350
351 template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
352     -> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) {
353     using size_type = typename Vector::size_type;
354
355     cl.def("__repr__",
356            [name](Vector &v) {
357             std::ostringstream s;
358             s << name << '[';
359             for (size_type i=0; i < v.size(); ++i) {
360                 s << v[i];
361                 if (i != v.size() - 1)
362                     s << ", ";
363             }
364             s << ']';
365             return s.str();
366         },
367         "Return the canonical string representation of this list."
368     );
369 }
370
371 // Provide the buffer interface for vectors if we have data() and we have a format for it
372 // GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data() is insufficient, we need to check it returns an appropriate pointer
373 template <typename Vector, typename = void>
374 struct vector_has_data_and_format : std::false_type {};
375 template <typename Vector>
376 struct vector_has_data_and_format<Vector, enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(), std::declval<Vector>().data()), typename Vector::value_type*>::value>> : std::true_type {};
377
378 // Add the buffer interface to a vector
379 template <typename Vector, typename Class_, typename... Args>
380 enable_if_t<detail::any_of<std::is_same<Args, buffer_protocol>...>::value>
381 vector_buffer(Class_& cl) {
382     using T = typename Vector::value_type;
383
384     static_assert(vector_has_data_and_format<Vector>::value, "There is not an appropriate format descriptor for this vector");
385
386     // numpy.h declares this for arbitrary types, but it may raise an exception and crash hard at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
387     format_descriptor<T>::format();
388
389     cl.def_buffer([](Vector& v) -> buffer_info {
390         return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
391     });
392
393     cl.def(init([](buffer buf) {
394         auto info = buf.request();
395         if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
396             throw type_error("Only valid 1D buffers can be copied to a vector");
397         if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
398             throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
399
400         auto vec = std::unique_ptr<Vector>(new Vector());
401         vec->reserve((size_t) info.shape[0]);
402         T *p = static_cast<T*>(info.ptr);
403         ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
404         T *end = p + info.shape[0] * step;
405         for (; p != end; p += step)
406             vec->push_back(*p);
407         return vec.release();
408     }));
409
410     return;
411 }
412
413 template <typename Vector, typename Class_, typename... Args>
414 enable_if_t<!detail::any_of<std::is_same<Args, buffer_protocol>...>::value> vector_buffer(Class_&) {}
415
416 NAMESPACE_END(detail)
417
418 //
419 // std::vector
420 //
421 template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
422 class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) {
423     using Class_ = class_<Vector, holder_type>;
424
425     // If the value_type is unregistered (e.g. a converting type) or is itself registered
426     // module-local then make the vector binding module-local as well:
427     using vtype = typename Vector::value_type;
428     auto vtype_info = detail::get_type_info(typeid(vtype));
429     bool local = !vtype_info || vtype_info->module_local;
430
431     Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
432
433     // Declare the buffer interface if a buffer_protocol() is passed in
434     detail::vector_buffer<Vector, Class_, Args...>(cl);
435
436     cl.def(init<>());
437
438     // Register copy constructor (if possible)
439     detail::vector_if_copy_constructible<Vector, Class_>(cl);
440
441     // Register comparison-related operators and functions (if possible)
442     detail::vector_if_equal_operator<Vector, Class_>(cl);
443
444     // Register stream insertion operator (if possible)
445     detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
446
447     // Modifiers require copyable vector value type
448     detail::vector_modifiers<Vector, Class_>(cl);
449
450     // Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive
451     detail::vector_accessor<Vector, Class_>(cl);
452
453     cl.def("__bool__",
454         [](const Vector &v) -> bool {
455             return !v.empty();
456         },
457         "Check whether the list is nonempty"
458     );
459
460     cl.def("__len__", &Vector::size);
461
462
463
464
465 #if 0
466     // C++ style functions deprecated, leaving it here as an example
467     cl.def(init<size_type>());
468
469     cl.def("resize",
470          (void (Vector::*) (size_type count)) & Vector::resize,
471          "changes the number of elements stored");
472
473     cl.def("erase",
474         [](Vector &v, SizeType i) {
475         if (i >= v.size())
476             throw index_error();
477         v.erase(v.begin() + i);
478     }, "erases element at index ``i``");
479
480     cl.def("empty",         &Vector::empty,         "checks whether the container is empty");
481     cl.def("size",          &Vector::size,          "returns the number of elements");
482     cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
483     cl.def("pop_back",                               &Vector::pop_back, "removes the last element");
484
485     cl.def("max_size",      &Vector::max_size,      "returns the maximum possible number of elements");
486     cl.def("reserve",       &Vector::reserve,       "reserves storage");
487     cl.def("capacity",      &Vector::capacity,      "returns the number of elements that can be held in currently allocated storage");
488     cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
489
490     cl.def("clear", &Vector::clear, "clears the contents");
491     cl.def("swap",   &Vector::swap, "swaps the contents");
492
493     cl.def("front", [](Vector &v) {
494         if (v.size()) return v.front();
495         else throw index_error();
496     }, "access the first element");
497
498     cl.def("back", [](Vector &v) {
499         if (v.size()) return v.back();
500         else throw index_error();
501     }, "access the last element ");
502
503 #endif
504
505     return cl;
506 }
507
508
509
510 //
511 // std::map, std::unordered_map
512 //
513
514 NAMESPACE_BEGIN(detail)
515
516 /* Fallback functions */
517 template <typename, typename, typename... Args> void map_if_insertion_operator(const Args &...) { }
518 template <typename, typename, typename... Args> void map_assignment(const Args &...) { }
519
520 // Map assignment when copy-assignable: just copy the value
521 template <typename Map, typename Class_>
522 void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
523     using KeyType = typename Map::key_type;
524     using MappedType = typename Map::mapped_type;
525
526     cl.def("__setitem__",
527            [](Map &m, const KeyType &k, const MappedType &v) {
528                auto it = m.find(k);
529                if (it != m.end()) it->second = v;
530                else m.emplace(k, v);
531            }
532     );
533 }
534
535 // Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting
536 template<typename Map, typename Class_>
537 void map_assignment(enable_if_t<
538         !is_copy_assignable<typename Map::mapped_type>::value &&
539         is_copy_constructible<typename Map::mapped_type>::value,
540         Class_> &cl) {
541     using KeyType = typename Map::key_type;
542     using MappedType = typename Map::mapped_type;
543
544     cl.def("__setitem__",
545            [](Map &m, const KeyType &k, const MappedType &v) {
546                // We can't use m[k] = v; because value type might not be default constructable
547                auto r = m.emplace(k, v);
548                if (!r.second) {
549                    // value type is not copy assignable so the only way to insert it is to erase it first...
550                    m.erase(r.first);
551                    m.emplace(k, v);
552                }
553            }
554     );
555 }
556
557
558 template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &cl, std::string const &name)
559 -> decltype(std::declval<std::ostream&>() << std::declval<typename Map::key_type>() << std::declval<typename Map::mapped_type>(), void()) {
560
561     cl.def("__repr__",
562            [name](Map &m) {
563             std::ostringstream s;
564             s << name << '{';
565             bool f = false;
566             for (auto const &kv : m) {
567                 if (f)
568                     s << ", ";
569                 s << kv.first << ": " << kv.second;
570                 f = true;
571             }
572             s << '}';
573             return s.str();
574         },
575         "Return the canonical string representation of this map."
576     );
577 }
578
579
580 NAMESPACE_END(detail)
581
582 template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
583 class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) {
584     using KeyType = typename Map::key_type;
585     using MappedType = typename Map::mapped_type;
586     using Class_ = class_<Map, holder_type>;
587
588     // If either type is a non-module-local bound type then make the map binding non-local as well;
589     // otherwise (e.g. both types are either module-local or converting) the map will be
590     // module-local.
591     auto tinfo = detail::get_type_info(typeid(MappedType));
592     bool local = !tinfo || tinfo->module_local;
593     if (local) {
594         tinfo = detail::get_type_info(typeid(KeyType));
595         local = !tinfo || tinfo->module_local;
596     }
597
598     Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
599
600     cl.def(init<>());
601
602     // Register stream insertion operator (if possible)
603     detail::map_if_insertion_operator<Map, Class_>(cl, name);
604
605     cl.def("__bool__",
606         [](const Map &m) -> bool { return !m.empty(); },
607         "Check whether the map is nonempty"
608     );
609
610     cl.def("__iter__",
611            [](Map &m) { return make_key_iterator(m.begin(), m.end()); },
612            keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
613     );
614
615     cl.def("items",
616            [](Map &m) { return make_iterator(m.begin(), m.end()); },
617            keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
618     );
619
620     cl.def("__getitem__",
621         [](Map &m, const KeyType &k) -> MappedType & {
622             auto it = m.find(k);
623             if (it == m.end())
624               throw key_error();
625            return it->second;
626         },
627         return_value_policy::reference_internal // ref + keepalive
628     );
629
630     cl.def("__contains__",
631         [](Map &m, const KeyType &k) -> bool {
632             auto it = m.find(k);
633             if (it == m.end())
634               return false;
635            return true;
636         }
637     );
638
639     // Assignment provided only if the type is copyable
640     detail::map_assignment<Map, Class_>(cl);
641
642     cl.def("__delitem__",
643            [](Map &m, const KeyType &k) {
644                auto it = m.find(k);
645                if (it == m.end())
646                    throw key_error();
647                m.erase(it);
648            }
649     );
650
651     cl.def("__len__", &Map::size);
652
653     return cl;
654 }
655
656 NAMESPACE_END(PYBIND11_NAMESPACE)