1#ifndef TATAMI_CHUNKED_CUSTOM_SPARSE_CHUNKED_MATRIX_HPP
2#define TATAMI_CHUNKED_CUSTOM_SPARSE_CHUNKED_MATRIX_HPP
5#include "custom_internals.hpp"
43namespace CustomChunkedMatrix_internal {
49template<
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
55 typename std::conditional<oracle_, size_t, bool>::type my_counter = 0;
58 typedef typename decltype(
my_factory)::Slab Slab;
77 my_coordinator(coordinator),
78 my_oracle(std::move(
oracle)),
81 coordinator.get_primary_chunkdim(
row),
82 coordinator.get_secondary_chunkdim(
row),
89 template<
typename ...
Args_>
92 i = my_oracle->get(my_counter++);
98template<
typename Value_,
typename Index_,
typename Chunk_>
99class MyopicSparseCore {
100 const ChunkCoordinator<Index_, true, Chunk_>& my_coordinator;
101 typename Chunk_::Workspace my_chunk_workspace;
103 SparseSlabFactory<typename Chunk_::value_type, Index_, Index_> my_factory;
104 typedef typename decltype(my_factory)::Slab Slab;
106 LruSlabCache<Index_, Slab> my_cache;
110 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
111 const SlabCacheStats& slab_stats,
114 Index_ secondary_length,
117 my_coordinator(coordinator),
118 my_factory(coordinator.get_primary_chunkdim(row), secondary_length, slab_stats, needs_value, needs_index),
119 my_cache(slab_stats.max_slabs_in_cache)
122 template<
typename ... Args_>
123 std::pair<const Slab*, Index_> fetch_raw(Index_ i,
bool row, Args_&& ... args) {
124 return my_coordinator.fetch_myopic(row, i, std::forward<Args_>(args)..., my_chunk_workspace, my_cache, my_factory);
128template<
typename Value_,
typename Index_,
typename Chunk_>
129class OracularSparseCore {
131 const ChunkCoordinator<Index_, true, Chunk_>& my_coordinator;
132 typename Chunk_::Workspace my_chunk_workspace;
134 SparseSlabFactory<typename Chunk_::value_type, Index_, Index_> my_factory;
135 typedef typename decltype(my_factory)::Slab Slab;
137 typename std::conditional<Chunk_::use_subset, OracularSubsettedSlabCache<Index_, Index_, Slab>, OracularSlabCache<Index_, Index_, Slab> >::type my_cache;
141 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
142 const SlabCacheStats& slab_stats,
145 Index_ secondary_length,
148 my_coordinator(coordinator),
149 my_factory(coordinator.get_primary_chunkdim(row), secondary_length, slab_stats, needs_value, needs_index),
150 my_cache(std::move(oracle), slab_stats.max_slabs_in_cache)
153 template<
typename ... Args_>
154 std::pair<const Slab*, Index_> fetch_raw([[maybe_unused]] Index_ i,
bool row, Args_&& ... args) {
155 return my_coordinator.fetch_oracular(row, std::forward<Args_>(args)..., my_chunk_workspace, my_cache, my_factory);
159template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
160using SparseCore =
typename std::conditional<solo_,
161 SoloSparseCore<oracle_, Value_, Index_, Chunk_>,
162 typename std::conditional<oracle_,
163 OracularSparseCore<Value_, Index_, Chunk_>,
164 MyopicSparseCore<Value_, Index_, Chunk_>
172template<
class Slab_,
typename Index_,
typename Value_>
173tatami::SparseRange<Value_, Index_> process_sparse_slab(
const std::pair<const Slab_*, Index_>& fetched, Value_* value_buffer, Index_* index_buffer,
bool needs_value,
bool needs_index) {
174 auto num = fetched.first->
number[fetched.second];
177 auto vptr = fetched.first->values[fetched.second];
178 std::copy_n(vptr, num, value_buffer);
184 auto iptr = fetched.first->indices[fetched.second];
185 std::copy_n(iptr, num, index_buffer);
193template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
197 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
198 const SlabCacheStats& slab_stats,
203 my_secondary_dim(coordinator.get_secondary_dim(row)),
204 my_needs_value(opt.sparse_extract_value),
205 my_needs_index(opt.sparse_extract_index),
212 opt.sparse_extract_value,
213 opt.sparse_extract_index
218 auto fetched = my_core.fetch_raw(i, my_row, 0, my_secondary_dim);
219 return process_sparse_slab(fetched, value_buffer, index_buffer, my_needs_value, my_needs_index);
224 Index_ my_secondary_dim;
225 bool my_needs_value, my_needs_index;
226 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
229template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
233 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
234 const SlabCacheStats& slab_stats,
241 my_block_start(block_start),
242 my_block_length(block_length),
243 my_needs_value(opt.sparse_extract_value),
244 my_needs_index(opt.sparse_extract_index),
257 auto fetched = my_core.fetch_raw(i, my_row, my_block_start, my_block_length);
258 return process_sparse_slab(fetched, value_buffer, index_buffer, my_needs_value, my_needs_index);
263 Index_ my_block_start, my_block_length;
264 bool my_needs_value, my_needs_index;
265 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
268template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
272 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
273 const SlabCacheStats& slab_stats,
279 my_indices_ptr(std::move(indices_ptr)),
280 my_needs_value(opt.sparse_extract_value),
281 my_needs_index(opt.sparse_extract_index),
287 my_indices_ptr->size(),
294 auto fetched = my_core.fetch_raw(i, my_row, *my_indices_ptr, my_tmp_indices);
295 return process_sparse_slab(fetched, value_buffer, index_buffer, my_needs_value, my_needs_index);
301 std::vector<Index_> my_tmp_indices;
302 bool my_needs_value, my_needs_index;
303 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
310template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
314 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
315 const SlabCacheStats& slab_stats,
320 my_secondary_dim(coordinator.get_secondary_dim(row)),
332 const Value_* fetch(Index_ i, Value_* buffer) {
333 auto contents = my_core.fetch_raw(i, my_row, 0, my_secondary_dim);
335 Index_ num = contents.first->number[contents.second];
336 auto vptr = contents.first->values[contents.second];
337 auto iptr = contents.first->indices[contents.second];
339 std::fill_n(buffer, my_secondary_dim, 0);
340 for (Index_ x = 0; x < num; ++x, ++iptr, ++vptr) {
341 buffer[*iptr] = *vptr;
348 Index_ my_secondary_dim;
349 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
352template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
356 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
357 const SlabCacheStats& slab_stats,
364 my_block_start(block_start),
365 my_block_length(block_length),
377 const Value_* fetch(Index_ i, Value_* buffer) {
378 auto contents = my_core.fetch_raw(i, my_row, my_block_start, my_block_length);
380 auto vptr = contents.first->values[contents.second];
381 auto iptr = contents.first->indices[contents.second];
382 auto num = contents.first->number[contents.second];
384 std::fill_n(buffer, my_block_length, 0);
385 for (Index_ x = 0; x < num; ++x, ++iptr, ++vptr) {
386 buffer[*iptr - my_block_start] = *vptr;
393 Index_ my_block_start, my_block_length;
394 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
397template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
401 const ChunkCoordinator<Index_, true, Chunk_>& coordinator,
402 const SlabCacheStats& slab_stats,
408 my_indices_ptr(std::move(indices_ptr)),
414 my_indices_ptr->size(),
419 const auto& indices = *my_indices_ptr;
420 if (!indices.empty()) {
421 my_remap_offset = indices.front();
422 size_t alloc = indices.back() - my_remap_offset + 1;
423 my_remap.resize(alloc);
425 for (
auto i : indices) {
426 my_remap[i - my_remap_offset] = counter;
432 const Value_* fetch(Index_ i, Value_* buffer) {
433 auto contents = my_core.fetch_raw(i, my_row, *my_indices_ptr, my_tmp_indices);
435 auto vptr = contents.first->values[contents.second];
436 auto iptr = contents.first->indices[contents.second];
437 auto num = contents.first->number[contents.second];
439 auto nidx = my_indices_ptr->size();
440 std::fill_n(buffer, nidx, 0);
441 for (Index_ x = 0; x <num; ++x, ++iptr, ++vptr) {
442 buffer[my_remap[*iptr - my_remap_offset]] = *vptr;
450 Index_ my_remap_offset = 0;
451 std::vector<Index_> my_remap;
452 std::vector<Index_> my_tmp_indices;
453 SparseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
475template<
typename Value_,
typename Index_,
typename Chunk_>
490 cache_size_in_bytes(
opt.maximum_cache_size),
491 require_minimum_cache(
opt.require_minimum_cache)
495 CustomChunkedMatrix_internal::ChunkCoordinator<Index_, true, Chunk_> coordinator;
496 size_t cache_size_in_bytes;
497 bool require_minimum_cache;
501 return coordinator.get_nrow();
504 Index_ ncol()
const {
505 return coordinator.get_ncol();
508 bool prefer_rows()
const {
509 return coordinator.prefer_rows_internal();
512 bool uses_oracle(
bool)
const {
516 double prefer_rows_proportion()
const {
517 return static_cast<double>(coordinator.prefer_rows_internal());
520 bool is_sparse()
const {
524 double is_sparse_proportion()
const {
537 template<
bool,
typename,
typename>
class Interface_,
539 template<
bool,
bool,
typename,
typename,
class>
class Extractor_,
542 std::unique_ptr<Interface_<oracle_, Value_, Index_> > raw_internal(
bool row, Index_ secondary_length,
const tatami::Options& opt, Args_&& ... args)
const {
543 size_t element_size = (opt.
sparse_extract_value ?
sizeof(
typename Chunk_::value_type) : 0) + (opt.sparse_extract_index ? sizeof(Index_) : 0);
547 SlabCacheStats stats(coordinator.get_chunk_nrow(), secondary_length, coordinator.get_num_chunks_per_column(), cache_size_in_bytes, element_size, require_minimum_cache);
548 if (stats.max_slabs_in_cache > 0) {
549 return std::make_unique<Extractor_<false, oracle_, Value_, Index_, Chunk_> >(coordinator, stats, row, std::forward<Args_>(args)...);
551 return std::make_unique<Extractor_<true, oracle_, Value_, Index_, Chunk_> >(coordinator, stats, row, std::forward<Args_>(args)...);
555 SlabCacheStats stats(coordinator.get_chunk_ncol(), secondary_length, coordinator.get_num_chunks_per_row(), cache_size_in_bytes, element_size, require_minimum_cache);
556 if (stats.max_slabs_in_cache > 0) {
557 return std::make_unique<Extractor_<false, oracle_, Value_, Index_, Chunk_> >(coordinator, stats, row, std::forward<Args_>(args)...);
559 return std::make_unique<Extractor_<true, oracle_, Value_, Index_, Chunk_> >(coordinator, stats, row, std::forward<Args_>(args)...);
564 template<
bool oracle_>
566 return raw_internal<tatami::DenseExtractor, oracle_, CustomChunkedMatrix_internal::DensifiedFull>(row, coordinator.get_secondary_dim(row), opt, std::move(oracle), opt);
569 template<
bool oracle_>
570 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
577 return raw_internal<tatami::DenseExtractor, oracle_, CustomChunkedMatrix_internal::DensifiedBlock>(row, block_length, opt, std::move(oracle), block_start, block_length, opt);
580 template<
bool oracle_>
581 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
587 auto num_indices = indices_ptr->size();
588 return raw_internal<tatami::DenseExtractor, oracle_, CustomChunkedMatrix_internal::DensifiedIndex>(row, num_indices, opt, std::move(oracle), std::move(indices_ptr), opt);
592 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row,
const tatami::Options& opt)
const {
593 return dense_internal<false>(row,
false, opt);
596 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
597 return dense_internal<false>(row,
false, block_start, block_length, opt);
601 return dense_internal<false>(row,
false, std::move(indices_ptr), opt);
608 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
613 return dense_internal<true>(row, std::move(oracle), opt);
616 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
623 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
626 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
632 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
639 template<
bool oracle_>
641 return raw_internal<tatami::SparseExtractor, oracle_, CustomChunkedMatrix_internal::SparseFull>(row, coordinator.get_secondary_dim(row), opt, std::move(oracle), opt);
644 template<
bool oracle_>
645 std::unique_ptr<tatami::SparseExtractor<oracle_, Value_, Index_> > sparse_internal(
652 return raw_internal<tatami::SparseExtractor, oracle_, CustomChunkedMatrix_internal::SparseBlock>(row, block_length, opt, std::move(oracle), block_start, block_length, opt);
655 template<
bool oracle_>
656 std::unique_ptr<tatami::SparseExtractor<oracle_, Value_, Index_> > sparse_internal(
662 auto num_indices = indices_ptr->size();
663 return raw_internal<tatami::SparseExtractor, oracle_, CustomChunkedMatrix_internal::SparseIndex>(row, num_indices, opt, std::move(oracle), std::move(indices_ptr), opt);
667 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row,
const tatami::Options& opt)
const {
668 return sparse_internal<false>(row,
false, opt);
671 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
672 return sparse_internal<false>(row,
false, block_start, block_length, opt);
676 return sparse_internal<false>(row,
false, std::move(indices_ptr), opt);
683 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
688 return sparse_internal<true>(row, std::move(oracle), opt);
691 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
698 return sparse_internal<true>(row, std::move(oracle), block_start, block_length, opt);
701 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
707 return sparse_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
Create a LRU cache of slabs.
Create a oracle-aware cache for slabs.
Create a oracle-aware cache with subsets.
Factory for sparse slabs.
Matrix of custom sparse chunks.
Definition CustomSparseChunkedMatrix.hpp:476
CustomSparseChunkedMatrix(Index_ mat_nrow, Index_ mat_ncol, Index_ chunk_nrow, Index_ chunk_ncol, std::vector< Chunk_ > chunks, bool row_major, const CustomSparseChunkedMatrixOptions &opt)
Definition CustomSparseChunkedMatrix.hpp:488
Methods to handle chunked tatami matrices.
Definition ChunkDimensionStats.hpp:4
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
typename std::conditional< oracle_, OracularSparseExtractor< Value_, Index_ >, MyopicSparseExtractor< Value_, Index_ > >::type SparseExtractor
typename std::conditional< oracle_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
std::shared_ptr< const std::vector< Index_ > > VectorPtr
bool sparse_extract_value
Statistics for regular chunks along a dimension.
Definition ChunkDimensionStats.hpp:35
Options for data extraction from a CustomSparseChunkedMatrix.
Definition CustomSparseChunkedMatrix.hpp:24
size_t maximum_cache_size
Definition CustomSparseChunkedMatrix.hpp:30
bool require_minimum_cache
Definition CustomSparseChunkedMatrix.hpp:37
Statistics for slab caching.
Definition SlabCacheStats.hpp:20