From cd59c85afab2034acea93ec3501d46a496394c47 Mon Sep 17 00:00:00 2001 From: LTLA Date: Thu, 3 Oct 2024 15:44:50 -0700 Subject: [PATCH] Accept a reference to Matrix by default, which is probably safer. This is more ergonomic and reduces the risk of using dangling pointers. --- CMakeLists.txt | 2 +- README.md | 2 +- .../convert_to_layered_sparse.hpp | 48 ++++++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb27c5a..8478023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(tatami_layered - VERSION 1.0.0 + VERSION 2.0.0 DESCRIPTION "Create layered tatami matrices" LANGUAGES CXX) diff --git a/README.md b/README.md index 0e5df07..9830cb0 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ We can easily convert an existing `tatami::Matrix` to a layered sparse matrix: ```cpp #include "tatami_layered/tatami_layered.hpp" -auto converted = tatami_layered::convert_to_layered_sparse(mat.get()); +auto converted = tatami_layered::convert_to_layered_sparse(*mat); ``` We can also read a layered sparse matrix from a Matrix Market file: diff --git a/include/tatami_layered/convert_to_layered_sparse.hpp b/include/tatami_layered/convert_to_layered_sparse.hpp index fc75986..8b2bbde 100644 --- a/include/tatami_layered/convert_to_layered_sparse.hpp +++ b/include/tatami_layered/convert_to_layered_sparse.hpp @@ -21,8 +21,8 @@ namespace tatami_layered { * @cond */ template -std::shared_ptr > convert_by_row(const tatami::Matrix* mat, IndexIn_ chunk_size, int nthreads) { - auto NR = mat->nrow(), NC = mat->ncol(); +std::shared_ptr > convert_by_row(const tatami::Matrix& mat, IndexIn_ chunk_size, int nthreads) { + auto NR = mat.nrow(), NC = mat.ncol(); IndexIn_ leftovers = NC % chunk_size; size_t nchunks = std::max(static_cast(1), static_cast(NC) / chunk_size + (leftovers != 0)); @@ -41,11 +41,11 @@ std::shared_ptr > convert_by_row(const tata for (auto& x : max_per_chunk) { x.resize(NR); } for (auto& x : num_per_chunk) { x.resize(NR); } - if (mat->sparse()) { + if (mat.sparse()) { tatami::parallelize([&](size_t, IndexIn_ start, IndexIn_ length) -> void { tatami::Options opt; opt.sparse_ordered_index = false; - auto ext = tatami::consecutive_extractor(mat, true, start, length, opt); + auto ext = tatami::consecutive_extractor(&mat, true, start, length, opt); std::vector dbuffer(NC); std::vector ibuffer(NC); @@ -64,7 +64,7 @@ std::shared_ptr > convert_by_row(const tata } else { tatami::parallelize([&](size_t, IndexIn_ start, IndexIn_ length) -> void { - auto ext = tatami::consecutive_extractor(mat, true, start, length); + auto ext = tatami::consecutive_extractor(&mat, true, start, length); std::vector dbuffer(NC); for (IndexIn_ r = start, end = start + length; r < end; ++r) { @@ -101,9 +101,9 @@ std::shared_ptr > convert_by_row(const tata std::vector output_positions(nchunks); std::vector dbuffer(NC); - if (mat->sparse()) { + if (mat.sparse()) { std::vector ibuffer(NC); - auto ext = tatami::consecutive_extractor(mat, true, start, length); + auto ext = tatami::consecutive_extractor(&mat, true, start, length); for (IndexIn_ r = start, end = start + length; r < end; ++r) { for (size_t chunk = 0; chunk < nchunks; ++chunk) { output_positions[chunk] = get_sparse_ptr(store8, store16, store32, assigned_category, assigned_position, chunk, r); @@ -120,7 +120,7 @@ std::shared_ptr > convert_by_row(const tata } } else { - auto ext = tatami::consecutive_extractor(mat, true, start, length); + auto ext = tatami::consecutive_extractor(&mat, true, start, length); for (IndexIn_ r = start, end = start + length; r < end; ++r) { for (size_t chunk = 0; chunk < nchunks; ++chunk) { output_positions[chunk] = get_sparse_ptr(store8, store16, store32, assigned_category, assigned_position, chunk, r); @@ -154,8 +154,8 @@ std::shared_ptr > convert_by_row(const tata } template -std::shared_ptr > convert_by_column(const tatami::Matrix* mat, IndexIn_ chunk_size, int nthreads) { - auto NR = mat->nrow(), NC = mat->ncol(); +std::shared_ptr > convert_by_column(const tatami::Matrix& mat, IndexIn_ chunk_size, int nthreads) { + auto NR = mat.nrow(), NC = mat.ncol(); IndexIn_ leftovers = NC % chunk_size; size_t nchunks = std::max(static_cast(1), static_cast(NC) / chunk_size + (leftovers != 0)); @@ -181,11 +181,11 @@ std::shared_ptr > convert_by_column(const t for (auto& x : num_per_chunk) { x.resize(NR); } } - if (mat->sparse()) { + if (mat.sparse()) { tatami::parallelize([&](size_t t, IndexIn_ start, IndexIn_ length) -> void { tatami::Options opt; opt.sparse_ordered_index = false; - auto ext = tatami::consecutive_extractor(mat, false, start, length, opt); + auto ext = tatami::consecutive_extractor(&mat, false, start, length, opt); std::vector dbuffer(NR); std::vector ibuffer(NR); auto& max_per_chunk = max_per_chunk_threaded[t]; @@ -210,7 +210,7 @@ std::shared_ptr > convert_by_column(const t } else { tatami::parallelize([&](size_t t, IndexIn_ start, IndexIn_ length) -> void { - auto ext = tatami::consecutive_extractor(mat, false, start, length); + auto ext = tatami::consecutive_extractor(&mat, false, start, length); std::vector dbuffer(NR); auto& max_per_chunk = max_per_chunk_threaded[t]; auto& num_per_chunk = num_per_chunk_threaded[t]; @@ -275,9 +275,9 @@ std::shared_ptr > convert_by_column(const t } } - if (mat->sparse()) { + if (mat.sparse()) { std::vector ibuffer(length); - auto ext = tatami::consecutive_extractor(mat, false, 0, NC, start, length); + auto ext = tatami::consecutive_extractor(&mat, false, 0, NC, start, length); for (IndexIn_ c = 0; c < NC; ++c) { auto range = ext->fetch(c, dbuffer.data(), ibuffer.data()); @@ -294,7 +294,7 @@ std::shared_ptr > convert_by_column(const t } } else { - auto ext = tatami::consecutive_extractor(mat, false, 0, NC, start, length); + auto ext = tatami::consecutive_extractor(&mat, false, 0, NC, start, length); for (IndexIn_ c = 0; c < NC; ++c) { auto ptr = ext->fetch(c, dbuffer.data()); @@ -352,19 +352,31 @@ std::shared_ptr > convert_by_column(const t * For example, if `ColumnIndex_` was set to an unsigned 8-bit integer, `chunk_size` would be automatically reduced to 256. */ template -std::shared_ptr > convert_to_layered_sparse(const tatami::Matrix* mat, IndexIn_ chunk_size = 65536, int num_threads = 1) { +std::shared_ptr > convert_to_layered_sparse(const tatami::Matrix& mat, IndexIn_ chunk_size = 65536, int num_threads = 1) { size_t max_index = static_cast(std::numeric_limits::max()) + 1; if (static_cast(chunk_size) > max_index) { chunk_size = max_index; } - if (mat->prefer_rows()) { + if (mat.prefer_rows()) { return convert_by_row(mat, chunk_size, num_threads); } else { return convert_by_column(mat, chunk_size, num_threads); } } +/** + * @cond + */ +// Provided for back-compatibility. +template +std::shared_ptr > convert_to_layered_sparse(const tatami::Matrix* mat, IndexIn_ chunk_size = 65536, int num_threads = 1) { + return convert_to_layered_sparse(*mat, chunk_size, num_threads); +} +/** + * @endcond + */ + } #endif