Data-KDTree-Shared

 view release on metacpan or  search on metacpan

Shared.xs  view on Meta::CPAN

     * 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 )