1#ifndef TATAMI_CHUNKED_CUSTOM_DENSE_CHUNKED_MATRIX_HPP
2#define TATAMI_CHUNKED_CUSTOM_DENSE_CHUNKED_MATRIX_HPP
5#include "custom_internals.hpp"
16#include "sanisizer/sanisizer.hpp"
55template<
typename ChunkValue_,
typename Index_>
104 Index_ chunk_column_id,
107 Index_ target_length,
108 Index_ non_target_start,
109 Index_ non_target_length,
145 Index_ chunk_column_id,
148 Index_ target_length,
149 const std::vector<Index_>& non_target_indices,
183 Index_ chunk_column_id,
185 const std::vector<Index_>& target_indices,
186 Index_ non_target_start,
187 Index_ non_target_length,
220 Index_ chunk_column_id,
222 const std::vector<Index_>& target_indices,
223 const std::vector<Index_>& non_target_indices,
234template<
typename ChunkValue_,
typename Index_>
253 virtual std::unique_ptr<CustomDenseChunkedMatrixWorkspace<ChunkValue_, Index_> >
new_workspace()
const = 0;
289namespace CustomChunkedMatrix_internal {
295template<
bool oracle_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
298 WorkspacePtr_ my_chunk_workspace;
299 const ChunkCoordinator<false, ChunkValue_, Index_>& my_coordinator;
302 typename std::conditional<oracle_, tatami::PredictionIndex, bool>::type my_counter = 0;
305 typedef typename decltype(my_factory)::Slab Slab;
312 DenseSingleWorkspace<ChunkValue_> my_tmp_solo;
315 typedef decltype(my_tmp_solo.size()) TmpSize;
319 WorkspacePtr_ chunk_workspace,
320 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
323 Index_ non_target_length
325 my_chunk_workspace(std::move(chunk_workspace)),
326 my_coordinator(coordinator),
327 my_oracle(std::move(oracle)),
328 my_factory(non_target_length, 1),
329 my_tmp_solo(
static_cast<TmpSize
>(my_coordinator.get_chunk_nrow()) *
static_cast<TmpSize
>(my_coordinator.get_chunk_ncol())),
330 my_final_solo(my_factory.
create())
333 template<
typename ... Args_>
334 std::pair<const Slab*, Index_> fetch_raw(
bool row, Index_ i, Args_&& ... args) {
335 if constexpr(oracle_) {
336 i = my_oracle->get(my_counter++);
338 return my_coordinator.fetch_single(row, i, std::forward<Args_>(args)..., *my_chunk_workspace, my_tmp_solo, my_final_solo);
342template<
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
343class MyopicDenseCore {
345 WorkspacePtr_ my_chunk_workspace;
346 const ChunkCoordinator<false, ChunkValue_, Index_>& my_coordinator;
348 DenseSlabFactory<ChunkValue_> my_factory;
349 typedef typename decltype(my_factory)::Slab Slab;
351 LruSlabCache<Index_, Slab> my_cache;
355 WorkspacePtr_ chunk_workspace,
356 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
357 const SlabCacheStats<Index_>& slab_stats,
359 [[maybe_unused]] Index_ non_target_length
361 my_chunk_workspace(std::move(chunk_workspace)),
362 my_coordinator(coordinator),
363 my_factory(slab_stats),
364 my_cache(slab_stats.max_slabs_in_cache)
367 template<
typename ... Args_>
368 std::pair<const Slab*, Index_> fetch_raw(
bool row, Index_ i, Args_&& ... args) {
369 return my_coordinator.fetch_myopic(row, i, std::forward<Args_>(args)..., *my_chunk_workspace, my_cache, my_factory);
373template<
bool use_subset_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
374class OracularDenseCore {
376 WorkspacePtr_ my_chunk_workspace;
377 const ChunkCoordinator<false, ChunkValue_, Index_>& my_coordinator;
379 DenseSlabFactory<ChunkValue_> my_factory;
380 typedef typename decltype(my_factory)::Slab Slab;
382 typename std::conditional<use_subset_, OracularSubsettedSlabCache<Index_, Index_, Slab>, OracularSlabCache<Index_, Index_, Slab> >::type my_cache;
386 WorkspacePtr_ chunk_workspace,
387 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
388 const SlabCacheStats<Index_>& slab_stats,
390 [[maybe_unused]] Index_ non_target_length
392 my_chunk_workspace(std::move(chunk_workspace)),
393 my_coordinator(coordinator),
394 my_factory(slab_stats),
395 my_cache(std::move(oracle), slab_stats.max_slabs_in_cache)
398 template<
typename ... Args_>
399 std::pair<const Slab*, Index_> fetch_raw(
bool row, [[maybe_unused]] Index_ i, Args_&& ... args) {
400 if constexpr(use_subset_) {
401 return my_coordinator.fetch_oracular_subsetted(row, std::forward<Args_>(args)..., *my_chunk_workspace, my_cache, my_factory);
403 return my_coordinator.fetch_oracular(row, std::forward<Args_>(args)..., *my_chunk_workspace, my_cache, my_factory);
408template<
bool solo_,
bool oracle_,
bool use_subset_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
409using DenseCore =
typename std::conditional<solo_,
410 SoloDenseCore<oracle_, Value_, Index_, ChunkValue_, WorkspacePtr_>,
411 typename std::conditional<oracle_,
412 OracularDenseCore<use_subset_, Value_, Index_, ChunkValue_, WorkspacePtr_>,
413 MyopicDenseCore<Value_, Index_, ChunkValue_, WorkspacePtr_>
421template<
class Slab_,
typename Index_,
typename Value_>
422const Value_* process_dense_slab(
const std::pair<const Slab_*, Index_>& fetched, Value_* buffer, Index_ non_target_length) {
423 auto ptr = fetched.first->data +
static_cast<std::size_t
>(fetched.second) *
static_cast<std::size_t
>(non_target_length);
424 std::copy_n(ptr, non_target_length, buffer);
428template<
bool solo_,
bool oracle_,
bool use_subset_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
432 WorkspacePtr_ chunk_workspace,
433 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
434 const SlabCacheStats<Index_>& slab_stats,
439 my_non_target_dim(coordinator.get_non_target_dim(row)),
441 std::move(chunk_workspace),
449 const Value_* fetch(Index_ i, Value_* buffer) {
450 auto fetched = my_core.fetch_raw(my_row, i, 0, my_non_target_dim);
451 return process_dense_slab(fetched, buffer, my_non_target_dim);
456 Index_ my_non_target_dim;
457 DenseCore<solo_, oracle_, use_subset_, Value_, Index_, ChunkValue_, WorkspacePtr_> my_core;
460template<
bool solo_,
bool oracle_,
bool use_subset_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
464 WorkspacePtr_ chunk_workspace,
465 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
466 const SlabCacheStats<Index_>& slab_stats,
473 my_block_start(block_start),
474 my_block_length(block_length),
476 std::move(chunk_workspace),
484 const Value_* fetch(Index_ i, Value_* buffer) {
485 auto fetched = my_core.fetch_raw(my_row, i, my_block_start, my_block_length);
486 return process_dense_slab(fetched, buffer, my_block_length);
491 Index_ my_block_start, my_block_length;
492 DenseCore<solo_, oracle_, use_subset_, Value_, Index_, ChunkValue_, WorkspacePtr_> my_core;
495template<
bool solo_,
bool oracle_,
bool use_subset_,
typename Value_,
typename Index_,
typename ChunkValue_,
class WorkspacePtr_>
499 WorkspacePtr_ chunk_workspace,
500 const ChunkCoordinator<false, ChunkValue_, Index_>& coordinator,
501 const SlabCacheStats<Index_>& slab_stats,
506 my_indices_ptr(std::move(indices_ptr)),
508 std::move(chunk_workspace),
512 my_indices_ptr->size()
516 const Value_* fetch(Index_ i, Value_* buffer) {
517 auto fetched = my_core.fetch_raw(my_row, i, *my_indices_ptr, my_tmp_indices);
518 return process_dense_slab(fetched, buffer,
static_cast<Index_
>(my_indices_ptr->size()));
524 std::vector<Index_> my_tmp_indices;
525 DenseCore<solo_, oracle_, use_subset_, Value_, Index_, ChunkValue_, WorkspacePtr_> my_core;
548template<
typename Value_,
typename Index_,
typename ChunkValue_,
class Manager_ = CustomDenseChunkedMatrixManager<ChunkValue_, Index_> >
556 my_manager(std::move(manager)),
557 my_coordinator(my_manager->row_stats(), my_manager->column_stats()),
558 my_cache_size_in_elements(opt.maximum_cache_size / sizeof(ChunkValue_)),
559 my_require_minimum_cache(opt.require_minimum_cache),
560 my_cache_subset(opt.cache_subset)
564 std::shared_ptr<Manager_> my_manager;
565 CustomChunkedMatrix_internal::ChunkCoordinator<false, ChunkValue_, Index_> my_coordinator;
566 std::size_t my_cache_size_in_elements;
567 bool my_require_minimum_cache;
568 bool my_cache_subset;
571 Index_ nrow()
const {
572 return my_coordinator.get_nrow();
575 Index_ ncol()
const {
576 return my_coordinator.get_ncol();
579 bool prefer_rows()
const {
580 return my_manager->prefer_rows();
583 bool uses_oracle(
bool)
const {
587 double prefer_rows_proportion()
const {
588 return static_cast<double>(my_manager->prefer_rows());
591 bool is_sparse()
const {
595 double is_sparse_proportion()
const {
607 template<
bool oracle_,
template<
bool,
bool,
bool,
typename,
typename,
typename,
class>
class Extractor_,
typename ... Args_>
608 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > raw_dense_internal(
bool row, Index_ non_target_length, Args_&& ... args)
const {
612 return SlabCacheStats<Index_>(my_coordinator.get_chunk_nrow(), non_target_length, my_coordinator.get_num_chunks_per_column(), my_cache_size_in_elements, my_require_minimum_cache);
615 return SlabCacheStats<Index_>(my_coordinator.get_chunk_ncol(), non_target_length, my_coordinator.get_num_chunks_per_row(), my_cache_size_in_elements, my_require_minimum_cache);
619 auto wrk = my_manager->new_workspace_exact();
620 if (stats.max_slabs_in_cache == 0) {
621 return std::make_unique<Extractor_<
true, oracle_,
false, Value_, Index_, ChunkValue_,
decltype(wrk)> >(std::move(wrk), my_coordinator, stats, row, std::forward<Args_>(args)...);
622 }
else if constexpr(oracle_) {
623 if (my_cache_subset) {
624 return std::make_unique<Extractor_<
false,
true,
true, Value_, Index_, ChunkValue_,
decltype(wrk)> >(std::move(wrk), my_coordinator, stats, row, std::forward<Args_>(args)...);
626 return std::make_unique<Extractor_<
false,
true,
false, Value_, Index_, ChunkValue_,
decltype(wrk)> >(std::move(wrk), my_coordinator, stats, row, std::forward<Args_>(args)...);
629 return std::make_unique<Extractor_<
false,
false,
false, Value_, Index_, ChunkValue_,
decltype(wrk)> >(std::move(wrk), my_coordinator, stats, row, std::forward<Args_>(args)...);
633 template<
bool oracle_>
635 auto non_target = (row ? my_coordinator.get_ncol() : my_coordinator.get_nrow());
636 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseFull>(row, non_target, std::move(oracle));
639 template<
bool oracle_>
640 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
647 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseBlock>(row, block_length, std::move(oracle), block_start, block_length);
650 template<
bool oracle_>
651 std::unique_ptr<tatami::DenseExtractor<oracle_, Value_, Index_> > dense_internal(
657 auto num_indices = indices_ptr->size();
658 return raw_dense_internal<oracle_, CustomChunkedMatrix_internal::DenseIndex>(row, num_indices, std::move(oracle), std::move(indices_ptr));
662 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row,
const tatami::Options& opt)
const {
663 return dense_internal<false>(row,
false, opt);
666 std::unique_ptr<tatami::MyopicDenseExtractor<Value_, Index_> > dense(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
667 return dense_internal<false>(row,
false, block_start, block_length, opt);
671 return dense_internal<false>(row,
false, std::move(indices_ptr), opt);
678 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
683 return dense_internal<true>(row, std::move(oracle), opt);
686 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
693 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
696 std::unique_ptr<tatami::OracularDenseExtractor<Value_, Index_> > dense(
702 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
709 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row,
const tatami::Options& opt)
const {
710 return std::make_unique<tatami::FullSparsifiedWrapper<false, Value_, Index_> >(dense(row, opt), my_coordinator.get_non_target_dim(row), opt);
713 std::unique_ptr<tatami::MyopicSparseExtractor<Value_, Index_> > sparse(
bool row, Index_ block_start, Index_ block_length,
const tatami::Options& opt)
const {
714 return std::make_unique<tatami::BlockSparsifiedWrapper<false, Value_, Index_> >(dense(row, block_start, block_length, opt), block_start, block_length, opt);
718 auto d = dense(row, indices_ptr, opt);
719 return std::make_unique<tatami::IndexSparsifiedWrapper<false, Value_, Index_> >(std::move(d), std::move(indices_ptr), opt);
726 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
731 return std::make_unique<tatami::FullSparsifiedWrapper<true, Value_, Index_> >(dense(row, std::move(oracle), opt), my_coordinator.get_non_target_dim(row), opt);
734 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
741 return std::make_unique<tatami::BlockSparsifiedWrapper<true, Value_, Index_> >(dense(row, std::move(oracle), block_start, block_length, opt), block_start, block_length, opt);
744 std::unique_ptr<tatami::OracularSparseExtractor<Value_, Index_> > sparse(
750 auto d = dense(row, std::move(oracle), indices_ptr, opt);
751 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.
Manager of chunks for a CustomDenseChunkedMatrix.
Definition CustomDenseChunkedMatrix.hpp:235
virtual const ChunkDimensionStats< Index_ > & row_stats() const =0
std::unique_ptr< CustomDenseChunkedMatrixWorkspace< ChunkValue_, Index_ > > new_workspace_exact() const
Definition CustomDenseChunkedMatrix.hpp:262
virtual const ChunkDimensionStats< Index_ > & column_stats() const =0
virtual std::unique_ptr< CustomDenseChunkedMatrixWorkspace< ChunkValue_, Index_ > > new_workspace() const =0
virtual bool prefer_rows() const =0
Workspace for extracting data from a CustomDenseChunkedMatrixManager.
Definition CustomDenseChunkedMatrix.hpp:56
virtual void extract(Index_ chunk_row_id, Index_ chunk_column_id, bool row, Index_ target_start, Index_ target_length, const std::vector< Index_ > &non_target_indices, ChunkValue_ *output, Index_ stride)=0
virtual void extract(Index_ chunk_row_id, Index_ chunk_column_id, bool row, const std::vector< Index_ > &target_indices, const std::vector< Index_ > &non_target_indices, ChunkValue_ *output, Index_ stride)=0
virtual void extract(Index_ chunk_row_id, Index_ chunk_column_id, bool row, const std::vector< Index_ > &target_indices, Index_ non_target_start, Index_ non_target_length, ChunkValue_ *output, Index_ stride)=0
virtual void extract(Index_ chunk_row_id, Index_ chunk_column_id, bool row, Index_ target_start, Index_ target_length, Index_ non_target_start, Index_ non_target_length, ChunkValue_ *output, Index_ stride)=0
Matrix of custom dense chunks.
Definition CustomDenseChunkedMatrix.hpp:549
CustomDenseChunkedMatrix(std::shared_ptr< Manager_ > manager, const CustomDenseChunkedMatrixOptions &opt)
Definition CustomDenseChunkedMatrix.hpp:555
Methods to handle chunked tatami matrices.
Definition ChunkDimensionStats.hpp:4
std::shared_ptr< const std::vector< Index_ > > VectorPtr
typename std::conditional< oracle_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
Statistics for regular chunks along a dimension.
Definition ChunkDimensionStats.hpp:35
Options for data extraction from a CustomDenseChunkedMatrix.
Definition CustomDenseChunkedMatrix.hpp:28
bool require_minimum_cache
Definition CustomDenseChunkedMatrix.hpp:41
std::size_t maximum_cache_size
Definition CustomDenseChunkedMatrix.hpp:34
bool cache_subset
Definition CustomDenseChunkedMatrix.hpp:47
Factory for dense slabs.
Definition DenseSlabFactory.hpp:29
Slab create()
Definition DenseSlabFactory.hpp:84
Statistics for slab caching.
Definition SlabCacheStats.hpp:26