89 const auto nblocks = blocks.size();
90 auto block_weights = sanisizer::create<std::vector<Distance_> >(nblocks);
92 sanisizer::cast<std::size_t>(nblocks),
93 [&](std::size_t b) -> Index_ {
return blocks[b].first; },
96 [&](std::size_t b, Distance_ w) ->
void { block_weights[b] = w; }
99 const auto total_weight = [&]{
100 quickstats::PairwiseSumWorkspace<Distance_> pswrk;
101 quickstats::PairwiseSumOptions psopt;
102 return quickstats::pairwise_sum(block_weights.size(), block_weights.data(), pswrk, psopt);
105 auto outputs = sanisizer::create<std::vector<std::pair<Distance_, Distance_> > >(nblocks);
107 for (I<decltype(nblocks)> b = start, bend = start + length; b < bend; ++b) {
108 const auto curweight = block_weights[b];
109 const auto curdist = compute_distance(blocks[b].first, blocks[b].second);
110 outputs[b].first = curdist.first * curweight;
111 outputs[b].second = curdist.second * curweight;
115 std::pair<Distance_, Distance_> output{};
116 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
117 output.first += outputs[b].first;
118 output.second += outputs[b].second;
122 output.first /= total_weight;
123 output.second /= total_weight;
152 Distance_*
const buffer,
155 const auto nblocks = prebuilts.size();
156 std::size_t accumulated = 0;
157 std::vector<std::pair<Index_, Distance_*> > blocks;
158 blocks.reserve(nblocks);
160 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
161 const auto nobs = prebuilts[b]->num_observations();
165 const auto searcher = prebuilts[b]->initialize();
166 std::vector<Distance_> cur_distances;
167 for (Index_ i = start, end = start + length; i < end; ++i) {
168 searcher->search(i, capped_k, NULL, &cur_distances);
169 if (cur_distances.size()) {
170 buffer[accumulated + i] = cur_distances.back();
172 buffer[accumulated + i] = 0;
177 blocks.emplace_back(nobs, buffer + accumulated);
181 return compute_distance_blocked(blocks, options);
213 const std::size_t num_dim,
214 const Index_ num_cells,
215 const Input_*
const data,
216 const Block_*
const blocks,
217 const std::size_t num_blocks,
219 Distance_*
const buffer,
223 auto block_details = sanisizer::create<std::vector<std::pair<Index_, Index_> > >(num_blocks);
224 Index_ non_contiguous = 0;
225 for (Index_ c = 0; c < num_cells; ++c) {
226 auto& curblock = block_details[blocks[c]];
227 if (curblock.second == 0) {
231 non_contiguous += (c != curblock.first + curblock.second);
236 const Input_* dataptr = data;
237 std::optional<std::vector<Input_> > tmp_data;
238 if (non_contiguous) {
240 Index_ accumulated = 0;
241 auto offsets = sanisizer::create<std::vector<Index_> >(num_blocks);
242 for (std::size_t b = 0; b < num_blocks; ++b) {
243 offsets[b] = accumulated;
244 block_details[b].first = accumulated;
245 accumulated += block_details[b].second;
248 tmp_data.emplace(sanisizer::product<
typename std::vector<Input_>::size_type>(num_dim, num_cells));
249 for (Index_ c = 0; c < num_cells; ++c) {
250 auto& off = offsets[blocks[c]];
252 data + sanisizer::product_unsafe<std::size_t>(c, num_dim),
254 tmp_data->data() + sanisizer::product_unsafe<std::size_t>(off, num_dim)
259 dataptr = tmp_data->data();
262 auto prebuilts = sanisizer::create<std::vector<std::shared_ptr<const knncolle::Prebuilt<Index_, Input_, Distance_> > > >(num_blocks);
264 for (std::size_t b = start, end = start + length; b < end; ++b) {
265 const auto sofar = block_details[b].first;
266 const auto cursize = block_details[b].second;
267 prebuilts[b] = builder.build_shared(knncolle::SimpleMatrix(num_dim, cursize, dataptr + sanisizer::product_unsafe<std::size_t>(sofar, num_dim)));
271 return compute_distance_blocked(prebuilts, buffer, options);