On Sat, Jan 24, 2015 at 6:48 AM, Simon King <simon...@uni-jena.de> wrote:
> I'd like to create a dictionary that is indexed by pairs of integers, and
> whose values are sets whose elements are pointers.
Technically, you need intptr_t, though practically any system modern
enough to have (C99) intptr_t is likely to have a memory addressing
scheme such that sizeof(size_t) == sizeof(intptr_t).
> Or, second bunch of questions: Is it possible to implement what I want (a
> dictionary indexed by pairs of integers yielding sets of pointers) in a
> different way, say, by using cython's c++ capabilities? If yes, how?
You could always introduce your own wrapper of void*(s) with a custom
hash and equality operator.
You could always introduce your own wrapper of void*(s) with a custom
hash and equality operator. Or implement the dictionary yourself (as
in https://github.com/sagemath/sagelib/blob/master/sage/structure/coerce_dict.pyx).
- Robert
cdef extern from "Python.h":
ctypedef int Py_intptr_t
See https://github.com/cython/cython/blob/master/tests/run/libcpp_all.pyx
for uses of std::map and std::set. The extra comparison template
parameter is not supported, you'd have to re-wrap it for that.
cdef class Dict2:
cdef dict data
def __init__(self):
self.data = dict()
def __getitem__(self,key):
return self.data[key]
def __setitem__(self, key,val):
cdef set S = self.data.setdefault(key, set())
S.add(val)
from libcpp.map cimport map as cmap
from libcpp.set cimport set as cset
from libcpp.pair cimport pair
from cython.operator cimport dereference as deref
ctypedef pair[int,int] intpair
ctypedef cset[int] intset
ctypedef cmap[intpair, intset] pair2set
cdef class Dict:
cdef pair2set data
def __dealloc__(self):
self.data.clear()
def __getitem__(self, key):
# Why does the following line NOT compile, ...
#cdef pair2set.iterator iter = self.data.find(<intpair>key)
# even though the following line DOES compile??
cdef cmap[intpair, intset].iterator iter = self.data.find(<intpair>key)
if iter != self.data.end():
# Why is deref() needed? I expected that, similar to using a <intpair*>,
# the member ".second" would be available without dereferencing.
return deref(iter).second
raise IndexError(key)
def __setitem__(self, key, val):
cdef intpair K = <intpair>key
# If K is an unknown key, then self.data[K] returns the empty set. Why
# is no error raised?
cdef intset S = self.data[K]
S.insert(<int>val)
# The previous line does NOT change the content of self.data[K], even if K is a
# known key. Why? I would like to do the insertion in-place, so that
# the following line is only needed when K has not been used before.
self.data[K] = S
def __setitem__(self, key, val):
cdef intpair K = <intpair>key
cdef intset S = self.data[K]
S.insert(<int>val)
self.data[K] = S
def __setitem__(self, key, val):
self.data[<intpair>key].insert(<int>val)
from libcpp.unordered_map cimport unordered_map
cdef extern from "<unordered_map>" namespace "std::tr1": ...
A duckduckgo-search taught me to doBut is that really correct? Can one not cimport Py_intptr_t from somewhere?
cdef extern from "Python.h":
ctypedef int Py_intptr_t
cdef extern from "Python.h":But is that really correct? Can one not cimport Py_intptr_t from somewhere?
ctypedef int Py_intptr_t
Perhaps I misunderstand: Isn't `ctypedef int Py_intptr_t` identifying Py_intptr_t with int, which is what we want to avoid?
std::unordered_map is a part of C++11 standard. You thus need to tell the
C++ compiler to use this standard instead of C++98 when compiling the
Cython code.
...
i don't remeber if Cython has std::unordered_map in its libcpp includes.
But if it does not it should look like the declaration of std::map.
cdef extern from "<boost/unordered_map.hpp>" namespace "boost":
cdef cppclass unordered_map[K, T]: # K: key_type, T: mapped_type
cppclass iterator:
pair& operator*()
bint operator==(iterator)
bint operator!=(iterator)
unordered_map()
bint empty()
size_t size()
iterator begin()
iterator end()
iterator find(K)
void clear()
size_t count(K)
T& operator[](K)
cdef extern from "<map>" namespace "std":
cdef cppclass multimap[K, T]: # K: key_type, T: mapped_type
cppclass iterator:
pair[K,T]& operator*()
iterator operator++()
bint operator==(iterator)
bint operator!=(iterator)
multimap()
bint empty()
size_t size()
iterator begin()
iterator end()
iterator find(K)
iterator insert(pair[K, T])
void erase(iterator)
pair[iterator, iterator] equal_range(K)
void clear()
size_t count(K)
A decision was made in the original STL to make std::map and std::set
binary search trees instead of hash tables, because under most
circumstances they performs better. ... In my own experience, the only STL container that can really help
speed-wise is std::vector, because it can both behave like a Python list
and a C array. It can give O(1) item access without Python overhead like
a C array, but appends are amortized O(1) like a Python list.
std::vector<T>::push_back is amortized O(1) and very fast.
Insertions in the middle is O(n).