|
""" |
|
Uses C++ map containers for fast dict-like behavior with keys being |
|
integers, and values float. |
|
""" |
|
|
|
|
|
|
|
|
|
from cython.operator cimport dereference as deref, preincrement as inc |
|
from libcpp.utility cimport pair |
|
from libcpp.map cimport map as cpp_map |
|
|
|
import numpy as np |
|
|
|
from ._typedefs cimport float64_t, intp_t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cdef class IntFloatDict: |
|
|
|
def __init__( |
|
self, |
|
intp_t[:] keys, |
|
float64_t[:] values, |
|
): |
|
cdef int i |
|
cdef int size = values.size |
|
|
|
|
|
for i in range(size): |
|
self.my_map[keys[i]] = values[i] |
|
|
|
def __len__(self): |
|
return self.my_map.size() |
|
|
|
def __getitem__(self, int key): |
|
cdef cpp_map[intp_t, float64_t].iterator it = self.my_map.find(key) |
|
if it == self.my_map.end(): |
|
|
|
raise KeyError('%i' % key) |
|
return deref(it).second |
|
|
|
def __setitem__(self, int key, float value): |
|
self.my_map[key] = value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __iter__(self): |
|
cdef int size = self.my_map.size() |
|
cdef intp_t [:] keys = np.empty(size, dtype=np.intp) |
|
cdef float64_t [:] values = np.empty(size, dtype=np.float64) |
|
self._to_arrays(keys, values) |
|
cdef int idx |
|
cdef intp_t key |
|
cdef float64_t value |
|
for idx in range(size): |
|
key = keys[idx] |
|
value = values[idx] |
|
yield key, value |
|
|
|
def to_arrays(self): |
|
"""Return the key, value representation of the IntFloatDict |
|
object. |
|
|
|
Returns |
|
======= |
|
keys : ndarray, shape (n_items, ), dtype=int |
|
The indices of the data points |
|
values : ndarray, shape (n_items, ), dtype=float |
|
The values of the data points |
|
""" |
|
cdef int size = self.my_map.size() |
|
keys = np.empty(size, dtype=np.intp) |
|
values = np.empty(size, dtype=np.float64) |
|
self._to_arrays(keys, values) |
|
return keys, values |
|
|
|
cdef _to_arrays(self, intp_t [:] keys, float64_t [:] values): |
|
|
|
cdef cpp_map[intp_t, float64_t].iterator it = self.my_map.begin() |
|
cdef cpp_map[intp_t, float64_t].iterator end = self.my_map.end() |
|
cdef int index = 0 |
|
while it != end: |
|
keys[index] = deref(it).first |
|
values[index] = deref(it).second |
|
inc(it) |
|
index += 1 |
|
|
|
def update(self, IntFloatDict other): |
|
cdef cpp_map[intp_t, float64_t].iterator it = other.my_map.begin() |
|
cdef cpp_map[intp_t, float64_t].iterator end = other.my_map.end() |
|
while it != end: |
|
self.my_map[deref(it).first] = deref(it).second |
|
inc(it) |
|
|
|
def copy(self): |
|
cdef IntFloatDict out_obj = IntFloatDict.__new__(IntFloatDict) |
|
|
|
out_obj.my_map = self.my_map |
|
return out_obj |
|
|
|
def append(self, intp_t key, float64_t value): |
|
|
|
cdef pair[intp_t, float64_t] args |
|
args.first = key |
|
args.second = value |
|
self.my_map.insert(args) |
|
|
|
|
|
|
|
|
|
|
|
def argmin(IntFloatDict d): |
|
cdef cpp_map[intp_t, float64_t].iterator it = d.my_map.begin() |
|
cdef cpp_map[intp_t, float64_t].iterator end = d.my_map.end() |
|
cdef intp_t min_key = -1 |
|
cdef float64_t min_value = np.inf |
|
while it != end: |
|
if deref(it).second < min_value: |
|
min_value = deref(it).second |
|
min_key = deref(it).first |
|
inc(it) |
|
return min_key, min_value |
|
|