81 const std::vector<
const tatami::Matrix<Value_, Index_>*>& representatives,
82 const std::vector<const Label_*>& labels,
85 auto nrefs = representatives.size();
86 if (nrefs != labels.size()) {
87 throw std::runtime_error(
"'representatives' and 'labels' should have the same length");
90 throw std::runtime_error(
"'representatives' should contain at least one entry");
92 auto ngenes = representatives.front()->nrow();
94 std::size_t nlabels = 0;
95 for (
decltype(nrefs) r = 0; r < nrefs; ++r) {
96 const auto& current = *representatives[r];
98 auto nrows = current.nrow();
99 if (nrows != ngenes) {
100 throw std::runtime_error(
"all entries of 'representatives' should have the same number of rows");
103 auto ncols = current.ncol();
105 auto curlab = labels[r];
106 nlabels = std::max(nlabels,
static_cast<std::size_t
>(*std::max_element(curlab, curlab + ncols)) + 1);
111 std::vector<std::vector<std::pair<bool, Index_> > > labels_to_index(nrefs);
112 for (
decltype(nrefs) r = 0; r < nrefs; ++r) {
113 auto& current = labels_to_index[r];
114 current.resize(nlabels);
115 auto ncols = representatives[r]->ncol();
116 auto curlab = labels[r];
118 for (
decltype(ncols) c = 0; c < ncols; ++c) {
119 auto& info = current[curlab[c]];
121 throw std::runtime_error(
"each label should correspond to no more than one column in each reference");
129 for (
auto& x : output) {
133 int actual_number = options.
number;
134 if (actual_number < 0) {
137 if (actual_number >
static_cast<int>(ngenes)) {
138 actual_number = ngenes;
142 std::vector<std::pair<Label_, Label_> > pairs;
144 std::set<std::pair<Label_, Label_> > pairs0;
145 for (
decltype(nrefs) r = 0; r < nrefs; ++r) {
146 auto ncols = representatives[r]->ncol();
147 auto curlab = labels[r];
148 for (
decltype(ncols) c1 = 0; c1 < ncols; ++c1) {
149 for (
decltype(c1) c2 = 0; c2 < c1; ++c2) {
150 pairs0.emplace(curlab[c1], curlab[c2]);
154 pairs.insert(pairs.end(), pairs0.begin(), pairs0.end());
157 auto npairs = pairs.size();
158 tatami::parallelize([&](
int,
decltype(npairs) start,
decltype(npairs) len) {
159 std::vector<std::pair<Value_, Index_> > sorter(ngenes);
160 std::vector<Value_> rbuffer(ngenes), lbuffer(ngenes);
161 std::vector<std::shared_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > > rextractors(nrefs), lextractors(nrefs);
163 for (
decltype(npairs) p = start, end = start + len; p < end; ++p) {
164 auto curleft = pairs[p].first;
165 auto curright = pairs[p].second;
167 for (
decltype(ngenes) g = 0; g < ngenes; ++g) {
169 sorter[g].second = g;
172 for (
decltype(nrefs) i = 0; i < nrefs; ++i) {
173 const auto& curavail = labels_to_index[i];
174 auto lcol = curavail[curleft];
175 auto rcol = curavail[curright];
176 if (!lcol.first || !rcol.first) {
181 auto& lext = lextractors[i];
183 lext = representatives[i]->dense_column();
185 auto lptr = lext->fetch(lcol.second, lbuffer.data());
187 auto& rext = rextractors[i];
189 rext = representatives[i]->dense_column();
191 auto rptr = rext->fetch(rcol.second, rbuffer.data());
193 for (
decltype(ngenes) g = 0; g < ngenes; ++g) {
194 sorter[g].first += lptr[g] - rptr[g];
201 for (
int flip = 0; flip < 2; ++flip) {
203 for (
auto& s : sorter) {
209 std::partial_sort(sorter.begin(), sorter.begin() + actual_number, sorter.end());
211 std::vector<Index_> stuff;
212 stuff.reserve(actual_number);
213 for (
int g = 0; g < actual_number && sorter[g].first < 0; ++g) {
214 stuff.push_back(sorter[g].second);
218 output[curleft][curright] = std::move(stuff);
220 output[curright][curleft] = std::move(stuff);