1#ifndef TATAMI_CHUNKED_CUSTOM_DENSE_CHUNKED_MATRIX_HPP
2#define TATAMI_CHUNKED_CUSTOM_DENSE_CHUNKED_MATRIX_HPP
5#include "custom_internals.hpp"
44namespace CustomChunkedMatrix_internal {
50template<
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
57 typename std::conditional<oracle_, size_t, bool>::type my_counter = 0;
60 typedef typename decltype(
my_factory)::Slab Slab;
76 my_coordinator(coordinator),
77 my_oracle(std::move(
oracle)),
79 my_tmp_solo(
static_cast<size_t>(my_coordinator.get_chunk_nrow()) *
static_cast<size_t>(my_coordinator.get_chunk_ncol())),
83 template<
typename ...
Args_>
86 i = my_oracle->get(my_counter++);
92template<
typename Value_,
typename Index_,
typename Chunk_>
93class MyopicDenseCore {
95 const ChunkCoordinator<Index_, false, Chunk_>& my_coordinator;
96 typename Chunk_::Workspace my_chunk_workspace;
98 DenseSlabFactory<typename Chunk_::value_type> my_factory;
99 typedef typename decltype(my_factory)::Slab Slab;
101 LruSlabCache<Index_, Slab> my_cache;
105 const ChunkCoordinator<Index_, false, Chunk_>& coordinator,
106 const SlabCacheStats& slab_stats,
108 [[maybe_unused]] Index_ secondary_length) :
109 my_coordinator(coordinator),
110 my_factory(slab_stats),
111 my_cache(slab_stats.max_slabs_in_cache)
114 template<
typename ... Args_>
115 std::pair<const Slab*, Index_> fetch_raw(
bool row, Index_ i, Args_&& ... args) {
116 return my_coordinator.fetch_myopic(row, i, std::forward<Args_>(args)..., my_chunk_workspace, my_cache, my_factory);
120template<
typename Value_,
typename Index_,
typename Chunk_>
121class OracularDenseCore {
123 const ChunkCoordinator<Index_, false, Chunk_>& my_coordinator;
124 typename Chunk_::Workspace my_chunk_workspace;
126 DenseSlabFactory<typename Chunk_::value_type> my_factory;
127 typedef typename decltype(my_factory)::Slab Slab;
129 typename std::conditional<Chunk_::use_subset, OracularSubsettedSlabCache<Index_, Index_, Slab>, OracularSlabCache<Index_, Index_, Slab> >::type my_cache;
133 const ChunkCoordinator<Index_, false, Chunk_>& coordinator,
134 const SlabCacheStats& slab_stats,
136 [[maybe_unused]] Index_ secondary_length) :
137 my_coordinator(coordinator),
138 my_factory(slab_stats),
139 my_cache(std::move(oracle), slab_stats.max_slabs_in_cache)
142 template<
typename ... Args_>
143 std::pair<const Slab*, Index_> fetch_raw(
bool row, [[maybe_unused]] Index_ i, Args_&& ... args) {
144 return my_coordinator.fetch_oracular(row, std::forward<Args_>(args)..., my_chunk_workspace, my_cache, my_factory);
148template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
149using DenseCore =
typename std::conditional<solo_,
150 SoloDenseCore<oracle_, Value_, Index_, Chunk_>,
151 typename std::conditional<oracle_,
152 OracularDenseCore<Value_, Index_, Chunk_>,
153 MyopicDenseCore<Value_, Index_, Chunk_>
161template<
class Slab_,
typename Index_,
typename Value_>
162const Value_* process_dense_slab(
const std::pair<const Slab_*, Index_>& fetched, Value_* buffer,
size_t secondary_length) {
163 auto ptr = fetched.first->data +
static_cast<size_t>(fetched.second) * secondary_length;
164 std::copy_n(ptr, secondary_length, buffer);
168template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
172 const ChunkCoordinator<Index_, false, Chunk_>& coordinator,
173 const SlabCacheStats& slab_stats,
177 my_secondary_dim(coordinator.get_secondary_dim(row)),
186 const Value_* fetch(Index_ i, Value_* buffer) {
187 auto fetched = my_core.fetch_raw(my_row, i, 0, my_secondary_dim);
188 return process_dense_slab(fetched, buffer, my_secondary_dim);
193 Index_ my_secondary_dim;
194 DenseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
197template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
201 const ChunkCoordinator<Index_, false, Chunk_>& coordinator,
202 const SlabCacheStats& slab_stats,
206 Index_ block_length) :
208 my_block_start(block_start),
209 my_block_length(block_length),
218 const Value_* fetch(Index_ i, Value_* buffer) {
219 auto fetched = my_core.fetch_raw(my_row, i, my_block_start, my_block_length);
220 return process_dense_slab(fetched, buffer, my_block_length);
225 Index_ my_block_start, my_block_length;
226 DenseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
229template<
bool solo_,
bool oracle_,
typename Value_,
typename Index_,
typename Chunk_>
233 const ChunkCoordinator<Index_, false, Chunk_>& coordinator,
234 const SlabCacheStats& slab_stats,
239 my_indices_ptr(std::move(indices_ptr)),
244 my_indices_ptr->size()
248 const Value_* fetch(Index_ i, Value_* buffer) {
249 auto fetched = my_core.fetch_raw(my_row, i, *my_indices_ptr, my_tmp_indices);
250 return process_dense_slab(fetched, buffer, my_indices_ptr->size());
256 std::vector<Index_> my_tmp_indices;
257 DenseCore<solo_, oracle_, Value_, Index_, Chunk_> my_core;
279template<
typename Value_,
typename Index_,
typename Chunk_>
295 my_require_minimum_cache(
opt.require_minimum_cache)
299 CustomChunkedMatrix_internal::ChunkCoordinator<Index_, false, Chunk_> my_coordinator;
300 size_t my_cache_size_in_elements;
301 bool my_require_minimum_cache;
305 return my_coordinator.get_nrow();
308 Index_ ncol()
const {
309 return my_coordinator.get_ncol();
312 bool prefer_rows()
const {
313 return my_coordinator.prefer_rows_internal();
316 bool uses_oracle(
bool)
const {
320 double prefer_rows_proportion()
const {
321 return static_cast<double>(my_coordinator.prefer_rows_internal());
324 bool is_sparse()
const {
328 double is_sparse_proportion()
const {
340 template<
bool oracle_,
template<
bool,
bool,
typename,
typename,
class>
class Extractor_,
typename ... Args_>
341 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > raw_dense_internal(
bool row, Index_ secondary_length, Args_&& ... args)
const {
344 SlabCacheStats stats(my_coordinator.get_chunk_nrow(), secondary_length, my_coordinator.get_num_chunks_per_column(), my_cache_size_in_elements, my_require_minimum_cache);
345 if (stats.max_slabs_in_cache > 0) {
346 return std::make_unique<Extractor_<false, oracle_, Value_, Index_, Chunk_> >(my_coordinator, stats, row, std::forward<Args_>(args)...);
348 return std::make_unique<Extractor_<true, oracle_, Value_, Index_, Chunk_> >(my_coordinator, stats, row, std::forward<Args_>(args)...);
352 SlabCacheStats stats(my_coordinator.get_chunk_ncol(), secondary_length, my_coordinator.get_num_chunks_per_row(), my_cache_size_in_elements, my_require_minimum_cache);
353 if (stats.max_slabs_in_cache > 0) {
354 return std::make_unique<Extractor_<false, oracle_, Value_, Index_, Chunk_> >(my_coordinator, stats, row, std::forward<Args_>(args)...);
356 return std::make_unique<Extractor_<true, oracle_, Value_, Index_, Chunk_> >(my_coordinator, stats, row, std::forward<Args_>(args)...);
361 template<
bool oracle_>
363 auto secondary = (row ? my_coordinator.get_ncol() : my_coordinator.get_nrow());
364 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseFull>(row, secondary, std::move(oracle));
367 template<
bool oracle_>
368 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
375 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseBlock>(row, block_length, std::move(oracle), block_start, block_length);
378 template<
bool oracle_>
379 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
385 auto num_indices = indices_ptr->size();
386 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseIndex>(row, num_indices, std::move(oracle), std::move(indices_ptr));
390 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row,
const tatami::Options& opt)
const {
391 return dense_internal<false>(row,
false, opt);
394 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
395 return dense_internal<false>(row,
false, block_start, block_length, opt);
399 return dense_internal<false>(row,
false, std::move(indices_ptr), opt);
406 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
411 return dense_internal<true>(row, std::move(oracle), opt);
414 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
421 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
424 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
430 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
437 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row,
const tatami::Options& opt)
const {
438 return std::make_unique<tatami::FullSparsifiedWrapper<false, Value_, Index_> >(dense(row, opt), my_coordinator.get_secondary_dim(row), opt);
441 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
442 return std::make_unique<tatami::BlockSparsifiedWrapper<false, Value_, Index_> >(dense(row, block_start, block_length, opt), block_start, block_length, opt);
446 auto d = dense(row, indices_ptr, opt);
447 return std::make_unique<tatami::IndexSparsifiedWrapper<false, Value_, Index_> >(std::move(d), std::move(indices_ptr), opt);
454 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
459 return std::make_unique<tatami::FullSparsifiedWrapper<true, Value_, Index_> >(dense(row, std::move(oracle), opt), my_coordinator.get_secondary_dim(row), opt);
462 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
469 return std::make_unique<tatami::BlockSparsifiedWrapper<true, Value_, Index_> >(dense(row, std::move(oracle), block_start, block_length, opt), block_start, block_length, opt);
472 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
478 auto d = dense(row, std::move(oracle), indices_ptr, opt);
479 return std::make_unique<tatami::IndexSparsifiedWrapper<true, Value_, Index_> >(std::move(d), 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.
Matrix of custom dense chunks.
Definition CustomDenseChunkedMatrix.hpp:280
CustomDenseChunkedMatrix(Index_ mat_nrow, Index_ mat_ncol, Index_ chunk_nrow, Index_ chunk_ncol, std::vector< Chunk_ > chunks, bool row_major, const CustomDenseChunkedMatrixOptions &opt)
Definition CustomDenseChunkedMatrix.hpp:292
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_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Statistics for regular chunks along a dimension.
Definition ChunkDimensionStats.hpp:35
Options for data extraction from a CustomDenseChunkedMatrix.
Definition CustomDenseChunkedMatrix.hpp:25
bool require_minimum_cache
Definition CustomDenseChunkedMatrix.hpp:38
size_t maximum_cache_size
Definition CustomDenseChunkedMatrix.hpp:31
Statistics for slab caching.
Definition SlabCacheStats.hpp:20