@@ -23,63 +23,105 @@ struct NeighborIndex {
2323
2424std::unique_ptr<knncolle::Builder<std::int32_t , double , double , knncolle::SimpleMatrix<std::int32_t , double > > > create_builder (bool );
2525
26- struct NeighborResults {
27- typedef std::vector<std::vector<std::pair<int32_t , double > > > Neighbors;
26+ class NeighborResults {
27+ typedef std::vector<std::vector<std::pair<std:: int32_t , double > > > Neighbors;
2828
29- Neighbors neighbors ;
29+ Neighbors my_neighbors ;
3030
3131public:
32- NeighborResults (size_t n = 0 ) : neighbors(n) {}
32+ NeighborResults () = default ;
3333
34- NeighborResults (size_t n, uintptr_t runs, uintptr_t indices, uintptr_t distances) : neighbors(n) {
35- auto rptr = reinterpret_cast <const int32_t *>(runs);
36- auto iptr = reinterpret_cast <const int32_t *>(indices);
34+ NeighborResults (Neighbors neighbors) : my_neighbors(std::move(neighbors)) {}
35+
36+ NeighborResults (JsFakeInt n_raw, JsFakeInt runs_raw, JsFakeInt indices_raw, JsFakeInt distances_raw) :
37+ my_neighbors (js2int<I<decltype (my_neighbors.size())> >(n_raw))
38+ {
39+ const auto runs = js2int<std::uintptr_t >(runs_raw);
40+ auto rptr = reinterpret_cast <const std::int32_t *>(runs);
41+
42+ const auto indices = js2int<std::uintptr_t >(indices_raw);
43+ auto iptr = reinterpret_cast <const std::int32_t *>(indices);
44+
45+ const auto distances = js2int<std::uintptr_t >(distances_raw);
3746 auto dptr = reinterpret_cast <const double *>(distances);
3847
39- for (size_t i = 0 ; i < n; ++i) {
40- neighbors[i].reserve (rptr[i]);
41- for (int32_t j = 0 ; j < rptr[i]; ++j, ++iptr, ++dptr) {
42- neighbors[i].emplace_back (*iptr, *dptr);
48+ const auto n = my_neighbors.size ();
49+ for (I<decltype (n)> i = 0 ; i < n; ++i) {
50+ const auto run = rptr[i];
51+ auto & nn = my_neighbors[i];
52+ nn.reserve (run);
53+
54+ for (I<decltype (run)> j = 0 ; j < run; ++j) {
55+ nn.emplace_back (iptr[j], dptr[j]);
4356 }
57+
58+ iptr += run;
59+ dptr += run;
4460 }
4561 }
4662
4763public:
48- double size (int32_t truncate) const {
49- size_t out = 0 ;
50- size_t long_truncate = truncate;
51- for (const auto & current : neighbors) {
52- out += std::min (long_truncate, current.size ());
64+ Neighbors& neighbors () {
65+ return my_neighbors;
66+ }
67+
68+ const Neighbors& neighbors () const {
69+ return my_neighbors;
70+ }
71+
72+ public:
73+ JsFakeInt size (JsFakeInt truncate_raw) const {
74+ std::size_t out = 0 ;
75+ if (truncate_raw < 0 ) {
76+ for (const auto & current : my_neighbors) {
77+ out = sanisizer::sum<std::size_t >(out, current.size ());
78+ }
79+ } else {
80+ const auto truncate = js2int<std::size_t >(truncate_raw);
81+ for (const auto & current : my_neighbors) {
82+ out = sanisizer::sum<std::size_t >(out, sanisizer::min (truncate, current.size ()));
83+ }
5384 }
54- return static_cast < double > (out);
85+ return int2js (out);
5586 }
5687
57- double num_obs () const {
58- return static_cast < double >(neighbors .size ());
88+ JsFakeInt num_obs () const {
89+ return int2js (my_neighbors .size ());
5990 }
6091
61- double num_neighbors () const {
62- return (neighbors .empty () ? 0 : neighbors .front ().size ());
92+ JsFakeInt num_neighbors () const {
93+ return int2js (my_neighbors .empty () ? 0 : my_neighbors .front ().size ());
6394 }
6495
65- void serialize (uintptr_t runs, uintptr_t indices, uintptr_t distances, int32_t truncate) const {
96+ void serialize (JsFakeInt runs_raw, JsFakeInt indices_raw, JsFakeInt distances_raw, JsFakeInt truncate_raw) const {
97+ const auto runs = js2int<std::uintptr_t >(runs_raw);
6698 auto rptr = reinterpret_cast <int32_t *>(runs);
99+
100+ const auto indices = js2int<std::uintptr_t >(indices_raw);
67101 auto iptr = reinterpret_cast <int32_t *>(indices);
102+
103+ const auto distances = js2int<std::uintptr_t >(distances_raw);
68104 auto dptr = reinterpret_cast <double *>(distances);
69105
70- size_t long_truncate = truncate;
71- for (const auto & current : neighbors) {
72- size_t nkeep = std::min (long_truncate, current.size ());
106+ const bool do_truncate = truncate_raw >= 0 ;
107+ const auto truncate = (do_truncate ? js2int<std::size_t >(truncate_raw) : 0 );
108+
109+ for (const auto & current : my_neighbors) {
110+ auto nkeep = current.size ();
111+ if (do_truncate && truncate < nkeep) {
112+ nkeep = truncate;
113+ }
73114 *rptr = nkeep;
74115 ++rptr;
75116
76- for (int32_t i = 0 ; i < nkeep; ++i) {
117+ for (I< decltype (nkeep)> i = 0 ; i < nkeep; ++i) {
77118 const auto & x = current[i];
78- *iptr = x.first ;
79- *dptr = x.second ;
80- ++iptr;
81- ++dptr;
119+ iptr[i] = x.first ;
120+ dptr[i] = x.second ;
82121 }
122+
123+ iptr += nkeep;
124+ dptr += nkeep;
83125 }
84126 }
85127};
0 commit comments