Data-KDTree-Shared
view release on metacpan or search on metacpan
* PID (dead-owner recovery never fires) -- a permanent shared-segment deadlock. */
int have_id = (SvGETMAGIC(id), SvOK(id));
uint64_t id_val = have_id ? (uint64_t)SvUV(id) : 0;
REEXTRACT(self); /* the id's get-magic is a second window */
kd_rwlock_wrlock(h);
payload = have_id ? id_val : h->hdr->count; /* default id = insertion index */
slot = kd_add_locked(h, buf, payload);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
kd_rwlock_wrunlock(h);
if (slot < 0) croak("Data::KDTree::Shared->add: tree is full (capacity %u)", (unsigned)h->capacity);
RETVAL = (UV)slot;
OUTPUT:
RETVAL
void
build(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
kd_rwlock_wrlock(h);
if (h->hdr->dirty) kd_build_locked(h);
kd_rwlock_wrunlock(h);
SV *
nearest(self, coords)
SV *self
SV *coords
PREINIT:
EXTRACT(self);
double buf[KD_MAX_DIMS];
KdRes best;
uint64_t found;
CODE:
kd_read_point(aTHX_ h, coords, buf, "nearest");
REEXTRACT(self); /* kd_read_point ran arbitrary Perl */
{
int wr = kd_query_lock(h);
found = kd_knn_locked(h, buf, 1, &best);
kd_query_unlock(h, wr);
}
if (found) {
HV *hv = newHV();
hv_stores(hv, "id", newSVuv((UV)best.id));
hv_stores(hv, "dist", newSVnv(sqrt(best.dist2)));
RETVAL = newRV_noinc((SV *)hv);
} else {
RETVAL = &PL_sv_undef; /* empty tree */
}
OUTPUT:
RETVAL
void
knn(self, coords, m)
SV *self
SV *coords
UV m
PREINIT:
EXTRACT(self);
double buf[KD_MAX_DIMS];
PPCODE:
kd_read_point(aTHX_ h, coords, buf, "knn");
REEXTRACT(self); /* kd_read_point ran arbitrary Perl */
{
KdRes *res = NULL;
uint64_t got = 0, i;
if (m > h->capacity) m = h->capacity; /* at most all points */
if (m) { Newx(res, (size_t)m, KdRes); SAVEFREEPV(res); } /* alloc BEFORE the lock */
{
int wr = kd_query_lock(h);
got = m ? kd_knn_locked(h, buf, m, res) : 0;
kd_query_unlock(h, wr);
}
if (got) qsort(res, (size_t)got, sizeof(KdRes), kd_res_cmp);
EXTEND(SP, (SSize_t)got);
for (i = 0; i < got; i++) {
HV *hv = newHV();
hv_stores(hv, "id", newSVuv((UV)res[i].id));
hv_stores(hv, "dist", newSVnv(sqrt(res[i].dist2)));
PUSHs(sv_2mortal(newRV_noinc((SV *)hv)));
}
}
void
range(self, lo, hi)
SV *self
SV *lo
SV *hi
PREINIT:
EXTRACT(self);
double blo[KD_MAX_DIMS], bhi[KD_MAX_DIMS];
PPCODE:
kd_read_point(aTHX_ h, lo, blo, "range");
REEXTRACT(self); /* kd_read_point ran arbitrary Perl */
kd_read_point(aTHX_ h, hi, bhi, "range");
REEXTRACT(self); /* kd_read_point ran arbitrary Perl */
{
uint64_t *ids = NULL, got = 0, i, cap = h->capacity;
if (cap) { Newx(ids, (size_t)cap, uint64_t); SAVEFREEPV(ids); } /* alloc BEFORE the lock */
{
int wr = kd_query_lock(h);
got = cap ? kd_range_locked(h, blo, bhi, ids, cap) : 0;
kd_query_unlock(h, wr);
}
EXTEND(SP, (SSize_t)got);
for (i = 0; i < got; i++) PUSHs(sv_2mortal(newSVuv((UV)ids[i])));
}
void
radius(self, coords, r)
SV *self
SV *coords
double r
PREINIT:
EXTRACT(self);
double buf[KD_MAX_DIMS];
PPCODE:
if (r < 0) croak("Data::KDTree::Shared->radius: radius must be >= 0");
kd_read_point(aTHX_ h, coords, buf, "radius");
REEXTRACT(self); /* kd_read_point ran arbitrary Perl */
{
KdRes *res = NULL;
uint64_t got = 0, i, cap = h->capacity;
if (cap) { Newx(res, (size_t)cap, KdRes); SAVEFREEPV(res); } /* alloc BEFORE the lock */
{
int wr = kd_query_lock(h);
got = cap ? kd_radius_locked(h, buf, r, res, cap) : 0;
kd_query_unlock(h, wr);
}
if (got) qsort(res, (size_t)got, sizeof(KdRes), kd_res_cmp);
EXTEND(SP, (SSize_t)got);
for (i = 0; i < got; i++) {
HV *hv = newHV();
hv_stores(hv, "id", newSVuv((UV)res[i].id));
hv_stores(hv, "dist", newSVnv(sqrt(res[i].dist2)));
PUSHs(sv_2mortal(newRV_noinc((SV *)hv)));
}
}
void
clear(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
kd_rwlock_wrlock(h);
kd_clear_locked(h);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
kd_rwlock_wrunlock(h);
UV
count(self)
SV *self
PREINIT:
EXTRACT(self);
UV n;
CODE:
kd_rwlock_rdlock(h);
n = (UV)h->hdr->count;
kd_rwlock_rdunlock(h);
RETVAL = n;
OUTPUT:
RETVAL
UV
capacity(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
RETVAL = (UV)h->hdr->capacity;
OUTPUT:
RETVAL
UV
dims(self)
SV *self
( run in 2.794 seconds using v1.01-cache-2.11-cpan-92ad3014f07 )