Support sparse matrices - #2
Open
bendichter wants to merge 1 commit into
Open
Conversation
v7.3 stores a sparse matrix as a group of three ordinary numeric datasets in compressed-column form: jc holds a running nonzero count per column plus a terminator, ir the 0-based row indices, and data the values. The indexer already handled all three (and complex data now that the compound path exists), so this is a reader-side change only. Two details are easy to get wrong and are what the tests aim at. The row count is not recoverable from the three datasets, since ir only names rows that actually hold a nonzero, so MATLAB records it in the MATLAB_sparse attribute; the column count is numel(jc) - 1. And a matrix with no nonzeros omits data and ir entirely, leaving a group with a single jc dataset, which is how both an all-zero matrix and sparse(0, 0) arrive. Sparse values are materialized eagerly, like cells and structs, rather than returned as a lazy zarr.Array. Zarr has no sparse concept to hang laziness on, and the compressed-column form has to be read in full to reconstruct any part of the matrix anyway. Testing covers both storage layouts (chunked + deflate, and contiguous via -nocompression) across the degenerate shapes: all-zero, 0x0, 0xN, single column, scalar, logical, logical all-zero, complex, and sparse nested inside a struct and a cell. Note that isequaln does not distinguish a sparse matrix from a full one with the same values, so the test asserts issparse and the class separately; without that it would pass on a reader that quietly returned dense matrices. Two sparse variables also join the shared round-trip matrix (now 21 types), which puts them through the HTTP and request-count tests. The synthetic survey corpus pairs complex and sparse in signals.mat as deliberate clean-error cases. Both now read, so the corpus surveys clean apart from the legacy v7 file, and the stale comments saying otherwise are updated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016nBFt7vk88uDoPpw2QQHFW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1 (targets
complex-compound, since the complex work is a prerequisite for sparse matrices with complex values). Retarget tomainonce #1 merges.v7.3 stores a sparse matrix as a group of three ordinary numeric datasets in compressed-column form:
jcholds a running nonzero count per column plus a terminator,irthe 0-based row indices, anddatathe values. The indexer already handled all three (and complexdata, now that #1 adds the compound path), so this is a reader-side change only: one newmaterializeSparseinFile.m.The two details worth knowing
The row count is not recoverable from the three datasets, since
ironly names rows that actually hold a nonzero. MATLAB records it in theMATLAB_sparseattribute; the column count isnumel(jc) - 1.A matrix with no nonzeros omits
dataandirentirely, leaving a group with a singlejcdataset. That is how both an all-zero matrix andsparse(0, 0)arrive.Eager, not lazy
Sparse values are materialized eagerly, like cells and structs. Zarr has no sparse concept to hang laziness on, and the compressed-column form has to be read in full to reconstruct any part of the matrix anyway.
Testing
Both storage layouts (chunked + deflate, and contiguous via
-nocompression) across the degenerate shapes: all-zero,0x0,0xN, single column, scalar, logical, logical all-zero, complex, and sparse nested inside a struct and a cell.Worth flagging:
isequalndoes not distinguish a sparse matrix from a full one with the same values, so the test assertsissparseand the class separately. Without that it would pass on a reader that quietly returned dense matrices.Two sparse variables also join the shared round-trip matrix (now 21 types), which puts them through the HTTP and request-count tests. 14/14 pass locally on R2024b.
Survey
tools/make_survey_corpus.mpairs complex and sparse insignals.matas deliberate clean-error cases. Both now read, so the corpus surveys clean apart from the legacy v7 file:The stale comments calling those paths clean-error cases are updated.
🤖 Generated with Claude Code
https://claude.ai/code/session_016nBFt7vk88uDoPpw2QQHFW