| Server IP : 217.160.0.135 / Your IP : 216.73.217.25 Web Server : Apache System : Linux www 6.18.52-i1-ampere #1203 SMP Mon Sep 14 18:29:59 CEST 2026 aarch64 User : sws1074145052 ( 1074145052) PHP Version : 8.3.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /lib/python3/dist-packages/pythran/pythonic/types/ |
Upload File : |
#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