← Back
Editing: set.hpp
#ifndef PYTHONIC_TYPES_SET_HPP #define PYTHONIC_TYPES_SET_HPP #include "pythonic/include/types/set.hpp" #include "pythonic/types/assignable.hpp" #include "pythonic/types/empty_iterator.hpp" #include "pythonic/types/list.hpp" #include "pythonic/utils/iterator.hpp" #include "pythonic/utils/reserve.hpp" #include "pythonic/utils/shared_ref.hpp" #include "pythonic/builtins/in.hpp" #include <set> #include <memory> #include <utility> #include <limits> #include <algorithm> #include <iterator> PYTHONIC_NS_BEGIN namespace types { /// set implementation // constructors template <class T> set<T>::set() : data(utils::no_memory()) { } template <class T> template <class InputIterator> set<T>::set(InputIterator start, InputIterator stop) : data() { std::copy(start, stop, std::back_inserter(*this)); } template <class T> set<T>::set(empty_set const &) : data() { } template <class T> set<T>::set(T const &value, single_value) : data() { data->insert(value); } template <class T> set<T>::set(std::initializer_list<value_type> l) : data(std::move(l)) { } template <class T> set<T>::set(set<T> const &other) : data(other.data) { } template <class T> template <class F> set<T>::set(set<F> const &other) : data() { std::copy(other.begin(), other.end(), std::inserter(*data, data->begin())); } // iterators template <class T> typename set<T>::iterator set<T>::begin() { return data->begin(); } template <class T> typename set<T>::const_iterator set<T>::begin() const { return data->begin(); } template <class T> typename set<T>::iterator set<T>::end() { return data->end(); } template <class T> typename set<T>::const_iterator set<T>::end() const { return data->end(); } template <class T> typename set<T>::reverse_iterator set<T>::rbegin() { return data->rbegin(); } template <class T> typename set<T>::const_reverse_iterator set<T>::rbegin() const { return data->rbegin(); } template <class T> typename set<T>::reverse_iterator set<T>::rend() { return data->rend(); } template <class T> typename set<T>::const_reverse_iterator set<T>::rend() const { return data->rend(); } // modifiers template <class T> T set<T>::pop() { if (size() <= 0) throw std::out_of_range("Trying to pop() an empty set."); T tmp = *begin(); data->erase(begin()); return tmp; } template <class T> void set<T>::add(const T &x) { data->insert(x); } template <class T> void set<T>::push_back(const T &x) { data->insert(x); } template <class T> void set<T>::clear() { data->clear(); } template <class T> template <class U> void set<T>::discard(U const &elem) { // Remove element elem from the set if it is present. data->erase(elem); } template <class T> template <class U> void set<T>::remove(U const &elem) { // Remove element elem from the set. Raises KeyError if elem is ! // contained in the set. if (!data->erase(elem)) throw std::runtime_error( "set.delete() : couldn't delete element ! in the set."); } // set interface template <class T> set<T>::operator bool() const { return !data->empty(); } template <class T> long set<T>::size() const { return data->size(); } // Misc template <class T> set<T> set<T>::copy() const { return set<T>(begin(), end()); } template <class T> template <class U> bool set<T>::isdisjoint(U const &other) const { // Return true if the this has no elements in common with other. for (iterator it = begin(); it != end(); ++it) { if (in(other, *it)) return false; } return true; } template <class T> template <class U> bool set<T>::issubset(U const &other) const { // Test whether every element in the set is in other. for (iterator it = begin(); it != end(); ++it) { if (!in(other, *it)) return false; } return true; } template <class T> template <class U> bool set<T>::issuperset(U const &other) const { // Test whether every element in other is in the set. return other.issubset(*this); } template <class T> set<T> set<T>::union_() const { return set<T>(begin(), end()); } template <class T> template <typename U, typename... Types> typename __combined<set<T>, U, Types...>::type set<T>::union_(U &&other, Types &&... others) const { typename __combined<set<T>, U, Types...>::type tmp = union_(std::forward<Types...>(others)...); tmp.data->insert(other.begin(), other.end()); return tmp; } template <class T> template <typename... Types> none_type set<T>::update(Types &&... others) { *this = union_(std::forward<Types>(others)...); return {}; } template <class T> set<T> set<T>::intersection() const { return set<T>(begin(), end()); } template <class T> template <typename U, typename... Types> typename __combined<set<T>, U, Types...>::type set<T>::intersection(U const &other, Types const &... others) const { // Return a new set with elements common to the set && all others. typename __combined<set<T>, U, Types...>::type tmp = intersection(others...); for (auto it = tmp.begin(); it != tmp.end(); ++it) { if (!in(other, *it)) tmp.discard( *it); // faster than remove() but ! direct interaction with data } return tmp; } template <class T> template <typename... Types> void set<T>::intersection_update(Types const &... others) { *this = intersection(others...); } template <class T> set<T> set<T>::difference() const { return set<T>(begin(), end()); } template <class T> template <typename U, typename... Types> set<T> set<T>::difference(U const &other, Types const &... others) const { // Return a new set with elements in the set that are ! in the others. set<T> tmp = difference(others...); /* for(iterator it=tmp.begin(); it!=tmp.end();++it){ if(other.get_data().find(*it)!=other.end()) tmp.discard(*it); } */ // This algo will do several times the same find(), because // std::set::erase() calls find. Lame! for (typename U::const_iterator it = other.begin(); it != other.end(); ++it) { tmp.discard(*it); } return tmp; } template <class T> template <class V> bool set<T>::contains(V const &v) const { return data->find(v) != data->end(); } template <class T> template <typename... Types> void set<T>::difference_update(Types const &... others) { *this = difference(others...); } template <class T> template <typename U> set<typename __combined<T, U>::type> set<T>::symmetric_difference(set<U> const &other) const { // Return a new set with elements in either the set || other but ! both. // return ((*this-other) | (other-*this)); // We must use fcts && ! operators because fcts have to handle any // iterable objects && operators only sets (cf python ref) return (this->difference(other)).union_(other.difference(*this)); } template <class T> template <typename U> typename __combined<U, set<T>>::type set<T>::symmetric_difference(U const &other) const { // Return a new set with elements in either the set || other but ! both. set<typename std::iterator_traits<typename U::iterator>::value_type> tmp( other.begin(), other.end()); // We must use fcts && ! operators because fcts have to handle any // iterable objects && operators only sets (cf python ref) return (this->difference(other)).union_(tmp.difference(*this)); } template <class T> template <typename U> void set<T>::symmetric_difference_update(U const &other) { *this = symmetric_difference(other); } // Operators template <class T> template <class U> bool set<T>::operator==(set<U> const &other) const { return *data == *other.data; } template <class T> template <class U> bool set<T>::operator<=(set<U> const &other) const { // Every element in *this is in other return issubset(other); } template <class T> template <class U> bool set<T>::operator<(set<U> const &other) const { // Every element in this is in other && this != other return (*this <= other) && (this->size() != other.size()); } template <class T> template <class U> bool set<T>::operator>=(set<U> const &other) const { // Every element in other is in set return other <= *this; } template <class T> template <class U> bool set<T>::operator>(set<U> const &other) const { // Every element in other is in set && this != other return other < *this; } template <class T> template <class U> set<typename __combined<T, U>::type> set<T>:: operator|(set<U> const &other) const { return union_(other); } template <class T> template <class U> void set<T>::operator|=(set<U> const &other) { update(other); } template <class T> template <class U> set<typename __combined<U, T>::type> set<T>:: operator&(set<U> const &other) const { return intersection(other); } template <class T> template <class U> void set<T>::operator&=(set<U> const &other) { return intersection_update(other); } template <class T> template <class U> set<T> set<T>::operator-(set<U> const &other) const { return difference(other); } template <class T> template <class U> void set<T>::operator-=(set<U> const &other) { return difference_update(other); } template <class T> template <class U> set<typename __combined<U, T>::type> set<T>:: operator^(set<U> const &other) const { return symmetric_difference(other); } template <class T> template <class U> void set<T>::operator^=(set<U> const &other) { return symmetric_difference_update(other); } template <class T> intptr_t set<T>::id() const { return reinterpret_cast<intptr_t>(&(*data)); } template <class T> std::ostream &operator<<(std::ostream &os, set<T> const &v) { if (v.size() == 0) { return os << "set()"; } os << "{"; const char *commaSeparator = ""; for (const auto &e : v) { os << commaSeparator << e; commaSeparator = ", "; } return os << "}"; } /// empty_set implementation empty_set empty_set::operator|(empty_set const &) { return empty_set(); } template <class T> set<T> empty_set::operator|(set<T> const &s) { return s; } template <class U> U empty_set::operator&(U const &s) { return {}; } template <class U> U empty_set::operator-(U const &s) { return {}; } empty_set empty_set::operator^(empty_set const &) { return empty_set(); } template <class T> set<T> empty_set::operator^(set<T> const &s) { return s; } template <class... Types> none_type empty_set::update(Types &&...) { return {}; } empty_set::operator bool() { return false; } empty_set::iterator empty_set::begin() const { return empty_iterator(); } empty_set::iterator empty_set::end() const { return empty_iterator(); } template <class V> bool empty_set::contains(V const &) const { return false; } } PYTHONIC_NS_END #ifdef ENABLE_PYTHON_MODULE PYTHONIC_NS_BEGIN template <typename T> PyObject *to_python<types::set<T>>::convert(types::set<T> const &v) { PyObject *obj = PySet_New(nullptr); for (auto const &e : v) PySet_Add(obj, ::to_python(e)); return obj; } PyObject *to_python<types::empty_set>::convert(types::empty_set) { return PySet_New(nullptr); } template <class T> bool from_python<types::set<T>>::is_convertible(PyObject *obj) { if (PySet_Check(obj)) { PyObject *iterator = PyObject_GetIter(obj); if (PyObject *item = PyIter_Next(iterator)) { bool res = ::is_convertible<T>(item); Py_DECREF(item); Py_DECREF(iterator); return res; } else { Py_DECREF(iterator); return true; } } return false; } template <class T> types::set<T> from_python<types::set<T>>::convert(PyObject *obj) { types::set<T> v = types::empty_set(); // may be useful to reserve more space ? PyObject *iterator = PyObject_GetIter(obj); while (PyObject *item = PyIter_Next(iterator)) { v.add(::from_python<T>(item)); Py_DECREF(item); } Py_DECREF(iterator); return v; } PYTHONIC_NS_END #endif #endif
Save File
Cancel