Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
182 commits
Select commit Hold shift + click to select a range
579cf28
Add an experimental Tensor: one by-row Matrix plus an axis layout
eriknw Oct 20, 2026
409f131
Tensor: cut per-op overhead of reductions; normalize only n x 1 results
eriknw Oct 20, 2026
74a6cfe
Tensor: add tensordot (no batch axes)
eriknw Oct 20, 2026
2fde74e
Tensor: fix reduction strategy picks; reshape relayout intermediates …
eriknw Oct 20, 2026
cbaf799
Tensor: bound the shape-only matrix cache by total entries
eriknw Oct 20, 2026
07fb05c
Tensor: core hooks, Matrix/Vector/ndarray operands, broadcasting
eriknw Oct 20, 2026
7df855f
Tensor: matmul and @ with numpy rules; batched products by block-diag…
eriknw Oct 20, 2026
3c4e204
Tensor: einsum, mttkrp, unfold, and a TTV path in tensordot
eriknw Oct 20, 2026
e0564f3
Tensor: extraction indexing, from_matrices/to_matrices
eriknw Oct 20, 2026
f708912
Tensor: TTV inside a group in one product; MTTKRP picks the cheapest …
eriknw Oct 20, 2026
7fd1a92
Tensor: look up infix operators when used, so the module imports with…
eriknw Oct 20, 2026
1a3d084
Tensor: MTTKRP reshapes in place only below 2^31, like relayout
eriknw Oct 20, 2026
dbca5ee
Tensor: lift broadcast operands to the result's rank before choosing …
eriknw Oct 20, 2026
cdd397f
Tensor: price PERM_R by expected nonempty rows and P's construction; …
eriknw Oct 20, 2026
3a53e03
Tensor: price selectors by group positions; build row-group ones from…
eriknw Oct 20, 2026
70cdd3a
Tensor: wide transposes and column sums on 2 threads; price reshapes …
eriknw Oct 20, 2026
f170115
Tensor: broadcast multiply by a gather onto the stored entries; cheap…
eriknw Oct 20, 2026
04393e3
Tensor: choose the default split before building; hypersparse rows ne…
eriknw Oct 20, 2026
093877d
Tensor: reprice reshapes into mostly empty rows; thin rows only for w…
eriknw Oct 20, 2026
bc6d683
Tensor: check the default split exactly below 2^23 entries; the filte…
eriknw Oct 20, 2026
9d2a230
Tensor: judge unsorted input's default split by a sample before building
eriknw Oct 20, 2026
b85b18c
Tensor: min_second for row permutations; a PERM_C edge through the Co…
eriknw Oct 20, 2026
62e45d5
Tensor: MTTKRP by Numba kernels over the stored arrays, in the stored…
eriknw Oct 20, 2026
f5a575f
Tensor: the planner tracks rows that come straight from a reshape
eriknw Oct 20, 2026
81a6ce5
Tensor: price a sorted REBUILD fallback only where reshape is unavail…
eriknw Oct 20, 2026
95424ef
Tensor: MTTKRP kernels for any number of axes; the products count the…
eriknw Oct 21, 2026
e4da79b
Tensor: MTTKRP over the first column axis by blocks of it, not per-th…
eriknw Oct 21, 2026
a223757
Tensor: test MTTKRP on layouts with an empty group
eriknw Oct 21, 2026
a6b9a25
Tensor: mask unions of Tensors; Scalar indices; CSR after a relayout …
eriknw Oct 21, 2026
e4682e7
Tensor: TTM by a Numba kernel over the stored arrays
eriknw Oct 21, 2026
d6cb059
Tensor: TTM in the stored order on hypersparse rows by a product on t…
eriknw Oct 21, 2026
8348112
Tensor: generated Numba kernels cached on disk
eriknw Oct 21, 2026
20d7c03
Tensor: use a kernel cache file only if it holds the kernel's source
eriknw Oct 21, 2026
4b37fac
Tensor: conversions with pydata/sparse and scipy.sparse n-d arrays
eriknw Oct 21, 2026
63be9b4
Tensor: TTM by one mxv with array-UDT values, the JIT's engine
eriknw Oct 21, 2026
dca166b
Tensor: the no-Numba MTTKRP's first product by the array-UDT engine
eriknw Oct 21, 2026
509c25c
Tensor: the UDT engine gives up cleanly when a JIT compile fails
eriknw Oct 21, 2026
4526614
Tensor: every TTM and MTTKRP engine selectable
eriknw Oct 21, 2026
3e5ec45
Tensor: UDT engine, no bitmap request on the empty output; test a new…
eriknw Oct 21, 2026
73daf1a
Tensor: reshape (numpy and Array API, C order), ravel, flatten
eriknw Oct 21, 2026
15f950a
Export gb.Tensor and gb.einsum (experimental)
eriknw Oct 21, 2026
434ed5c
Tensor: docstrings marked experimental, the module docstring brought …
eriknw Oct 21, 2026
f3d625c
Docs: a user guide page for the experimental Tensor, and its API refe…
eriknw Oct 21, 2026
433cb2e
Tensor: a TensorExpression offers the Tensor's methods, as Matrix exp…
eriknw Oct 21, 2026
27f295b
Tensor: index assignment, as Matrix assigns
eriknw Oct 21, 2026
09dffbc
Tensor: outer indexing with repeated indices repeats the entries
eriknw Oct 21, 2026
8ae7c09
Tensor: take, take_along_axis and vindex (vectorized gather)
eriknw Oct 21, 2026
753909b
Tensor: the GraphBLAS gather engine keys each point by one int64
eriknw Oct 21, 2026
a89c6a7
Tensor: reduce with aggregators; isequal and isclose with a Matrix, V…
eriknw Oct 21, 2026
e6e4872
docs: Tensor assignment by index, gathering, and reduce with aggregators
eriknw Oct 21, 2026
0c619ea
Tensor: take with numpy's mode ('raise', 'wrap', 'clip')
eriknw Oct 21, 2026
d9cc44e
docs: Tensor take's mode
eriknw Oct 21, 2026
2d7ccb1
Tensor: drop a guard on the hypersparse row pick that could not fire
eriknw Oct 21, 2026
812d34b
Tensor: name the positional aggregators by their agg.ss spelling in r…
eriknw Oct 21, 2026
47c9955
docs: Tensor reduce's unsupported aggregators by names that exist (ag…
eriknw Oct 21, 2026
0952189
Tensor: einsum plans once per subscripts and shapes, and runs one-ste…
eriknw Oct 21, 2026
e8c39a9
Tensor: let SuiteSparse choose the block-diagonal operand's format in…
eriknw Oct 21, 2026
1dccd95
Tensor: einsum's last contraction runs on the target, so a mask reach…
eriknw Oct 21, 2026
074e922
docs: Tensor contractions do not keep a moved operand; relayout one u…
eriknw Oct 21, 2026
74f53ff
Tensor: a private census of the decision points (off by default, for …
eriknw Oct 21, 2026
57468ac
Tensor: one rule for a full row group (FULL_ROW_ENTRIES, full_split)
eriknw Oct 21, 2026
ef63c9a
Tensor: the broadcast offers its relayout option only for another axi…
eriknw Oct 21, 2026
8f54d6a
Tensor: the compacted TTM is the products engine's hypersparse branch…
eriknw Oct 21, 2026
d6eee03
Tensor: allow_perm gates PERM_C as well as PERM_R
eriknw Oct 21, 2026
a389ac9
Tensor kernel cache: a rename that loses a race to another process us…
eriknw Oct 21, 2026
ca19119
Tensor: the test modules skip on a SuiteSparse without the Container …
eriknw Oct 21, 2026
a84a0c8
Tensor: the 10.5.1 in-place reshape workaround in one helper, with a …
eriknw Oct 21, 2026
049e266
Tensor: the UDT TTM engine's hypersparse output is SuiteSparse's (und…
eriknw Oct 21, 2026
27d97d0
Tensor planner: price a transpose out of the source on its sampled no…
eriknw Oct 21, 2026
0d8625c
Tensor broadcast: a split move into hypersparse rows pays the diagona…
eriknw Oct 21, 2026
e4c0266
Tensor: move reshape, element-wise / broadcasting and reductions into…
eriknw Oct 21, 2026
beea1ec
Tensor: move contractions and the TTM / MTTKRP engines into their own…
eriknw Oct 21, 2026
d333458
Tensor: move einsum into its own module, and extraction next to assig…
eriknw Oct 21, 2026
664d511
Tensor: comments and test headings state their reasons in place
eriknw Oct 21, 2026
594019f
Tensor: graphblas.core.tensor re-exports _orders again, as before the…
eriknw Oct 21, 2026
5e1ecee
Add ai-notes for the experimental Tensor
eriknw Oct 21, 2026
037cf85
Tensor: eight more comments and docstrings state their reasons in place
eriknw Oct 21, 2026
151c63d
ai-notes: write the SuiteSparse:GraphBLAS wishlist for the Tensor
eriknw Oct 21, 2026
ffb92ee
benchmarks: asv benchmarks for the experimental Tensor
eriknw Oct 21, 2026
d05ac20
scripts/tensor_bench: a portable benchmark kit for the experimental T…
eriknw Oct 21, 2026
8bc63ae
scripts/tensor_bench: fixes from the run in a fresh clone
eriknw Oct 21, 2026
b942b19
ai-notes: write the Tensor's benchmarks page
eriknw Oct 21, 2026
923be33
Matrix and Vector isequal / isclose compare with a Tensor too
eriknw Oct 21, 2026
8a4490d
Tensor TTM: the array-UDT engine declines a product SuiteSparse marks…
eriknw Oct 21, 2026
a656b4a
Tensor: randomized oracles as slow tests, with teeth
eriknw Oct 22, 2026
0b72b38
Tensor oracles: the assignment teeth use replace on every masked case
eriknw Oct 22, 2026
7ac54bf
CI: the notebook job skips the Tensor notebooks without SuiteSparse:G…
eriknw Oct 22, 2026
6a5c592
Tensor notebooks: a quickstart, and multiplex PageRank on EU airlines
eriknw Oct 22, 2026
82adaf3
ai-notes: name the benchmarked commits by subject, not by id
eriknw Oct 27, 2026
1565fee
Tensor tests: skip the Numba tests on any ImportError, as the library…
eriknw Oct 27, 2026
72de09c
Tensor kernel cache test: no read-only check where a directory stays …
eriknw Oct 27, 2026
f164b03
Tensor: delete and assign empty values as GrB_Scalars, for CI's C-sca…
eriknw Oct 27, 2026
66453d9
Tensor relayout test: non-iso BOOL values that are not all True
eriknw Oct 27, 2026
582fb77
Tensor: hand arrays to SuiteSparse with suitesparse-graphblas < 10.5.…
eriknw Oct 27, 2026
c199f37
Tensor kernel cache test: reap both processes when one fails
eriknw Oct 27, 2026
0bff138
test_core: test_tensor_exports expects the Tensor's refusal on SuiteS…
eriknw Oct 27, 2026
05c3b77
test_core: test_tensor_exports asks the subprocess whether the Tensor…
eriknw Oct 27, 2026
30ac41a
Tensor: refuse n-d scipy.sparse conversion clearly when scipy is olde…
eriknw Oct 27, 2026
55c9f49
test_tensor_io: compare a 0-d pydata COO by its value, not by its tod…
eriknw Oct 27, 2026
9c20417
Tensor PageRank notebook: check the CSVs' hashes, not the zip's
eriknw Oct 27, 2026
98f9604
tensor_bench fetch_data: check eu-airlines by its CSVs, not by the zip
eriknw Oct 27, 2026
5f4b51c
Tensor test: the JIT-failure test's Numba case skips without Numba
eriknw Oct 27, 2026
c012688
Tensor tests: read a 2-d scipy COO's coordinates from row and col
eriknw Oct 27, 2026
a18588c
Tensor user guide doctest: ignore numpy's int64 dtype where int is 32…
eriknw Oct 27, 2026
2003868
tensor_bench: run the Tensor at a chosen SuiteSparse JIT mode
eriknw Oct 27, 2026
add2113
Tensor: BOOL selector products with lor_land, which SuiteSparse preco…
eriknw Oct 27, 2026
bc25590
Tensor: the UDT TTM engine leaves the JIT control alone when it declines
eriknw Oct 27, 2026
ac46e71
ai-notes: the Tensor's benchmarks with the JIT on, run and off
eriknw Oct 27, 2026
a8dfbe1
Tensor PageRank notebook: retry the download after a server error or …
eriknw Oct 27, 2026
a5a577c
Tensor: take_along_axis reads coordinate 0 along a size-1 axis it bro…
eriknw Oct 27, 2026
bde545d
Tensor: finish a stored Matrix before testing its format for Containe…
eriknw Oct 27, 2026
bd6a442
Tensor: Numba TTM and MTTKRP kernels read 64-bit row pointers as int64
eriknw Oct 27, 2026
2629598
Tensor: C << V takes V's layout when V is a view of the store C shares
eriknw Oct 27, 2026
cc2875d
Tensor: reductions and products of an operand with no entries give none
eriknw Oct 27, 2026
2793a05
Tensor: einsum and MTTKRP group terms only as far as the semiring allows
eriknw Oct 27, 2026
169ed2f
Tensor: products flip an op only to one of the same kind (pow, not rpow)
eriknw Oct 27, 2026
9207cd9
Tensor: a GCXS with repeated or unsorted columns imports as pydata re…
eriknw Oct 27, 2026
1ef56c5
Tensor: the array-UDT engine claims its type's C name in the UDT regi…
eriknw Oct 27, 2026
2c815ef
Tensor: broadcast, TTV and assignment past 2^63 positions in total
eriknw Oct 27, 2026
3b01b3c
Tensor: indexing costs follow the entries and the index, not the axis…
eriknw Oct 27, 2026
81489b3
Tensor: the GraphBLAS gather finds hits by binary search past 2^63 po…
eriknw Oct 27, 2026
1693f1b
Tensor: after a failed compile the array-UDT engine leaves the JIT co…
eriknw Oct 27, 2026
ad0af43
Tensor: -X, abs(X), ~X and select with a string op, as for Matrix
eriknw Oct 27, 2026
ed0bff4
Tensor: refuse 1-d and 2-d axes past 2^60 clearly; doc notes from the…
eriknw Oct 27, 2026
828e748
Tensor: einsum takes an explicit path as given, or refuses it clearly
eriknw Oct 27, 2026
2c8b4db
Tensor: remove branches that cannot run
eriknw Oct 28, 2026
e7d64c6
Tensor: exclude the Numba kernels and two safety guards from coverage
eriknw Oct 28, 2026
599836a
Tensor tests: drop checks that cannot fail, and mark failure-only lines
eriknw Oct 28, 2026
a5ac3d3
Tensor tests: cover operands, expressions, in-place and infix paths
eriknw Oct 28, 2026
8c607e3
Tensor tests: cover reductions, contractions, einsum, indexing, resha…
eriknw Oct 28, 2026
18126e7
Tensor tests: cover the TTM and MTTKRP engines, the kernel cache and …
eriknw Oct 28, 2026
5f88f9e
Tensor tests: cover the census's notes, forced paths and environment …
eriknw Oct 28, 2026
a8344f1
Tensor: from_dense's Matrix is held by row already
eriknw Oct 28, 2026
9b16fa7
Tensor tests: a full TTV weight over hypersparse rows takes the row s…
eriknw Oct 28, 2026
6fd941d
Tensor: a broadcast ewise_mult with no option left looks up the small…
eriknw Oct 28, 2026
07adf5b
Tensor: the Numba TTM declines when its output rows pass 2^60
eriknw Oct 28, 2026
70cd51b
Tensor: a TTV past 2^60 positions goes through the entries
eriknw Oct 28, 2026
e3e1535
Tensor: an extraction as an operand is computed, or refused with the …
eriknw Oct 28, 2026
1ea7b6e
Tensor: C << T[idx] stores the extraction, as for Matrix
eriknw Oct 28, 2026
4723016
Tensor: say that einsum's regrouping is exact up to integer overflow
eriknw Oct 28, 2026
c115bd6
Tensor: the reasons in _ttm_numba's and _lookup_numba's comments
eriknw Oct 28, 2026
43738d7
Tensor: price the extract by the rows it visits
eriknw Oct 28, 2026
7604b33
Tensor: take a row as a Vector without an extract
eriknw Oct 28, 2026
74c3fe0
Tensor: filter a column range of sparse rows in place
eriknw Oct 28, 2026
ddb1b96
Tensor: price many relayout targets from one planner search
eriknw Oct 28, 2026
cc3bac9
Tensor: sum unsigned data with a row selector typed like it
eriknw Oct 28, 2026
db30399
Tensor notes: where TTM's time goes off the stored order, and the A/B…
eriknw Oct 28, 2026
185b3ea
Tensor: take a by-column row as a Vector too
eriknw Oct 28, 2026
db74526
Tensor: Review 4's wording fixes, and a stolen row keeps its sparsity…
eriknw Oct 28, 2026
c64de96
Tensor: document wait()'s row hash and the choice of no per-mode copies
eriknw Oct 28, 2026
d48f7ad
Tensor: Review 5's nits on wait(), which now returns the Tensor
eriknw Oct 28, 2026
fb643d5
Tensor: C << (X | Y), (X & Y), (X @ Y) and X ^ Y, as Matrix takes them
eriknw Oct 28, 2026
c0c22e0
ai-notes: broadcast unions with broadcast axes split across groups st…
eriknw Oct 28, 2026
54afc2f
ai-notes: the row hash that the Tensor's internal waits build, as a r…
eriknw Oct 28, 2026
0788a40
Tensor: X | Y and X & Y on their own follow Matrix: BOOL only
eriknw Oct 28, 2026
359cd76
Tensor: broadcast onto nonempty rows finds values by search, not a de…
eriknw Oct 28, 2026
0241894
Tensor: size four more paths by the entries, not by a long axis or group
eriknw Oct 28, 2026
bc701e8
Tensor: keep the cached selector where it fits, and find values witho…
eriknw Oct 28, 2026
ac3fdf1
Tensor: say what a GCXS export's row pointer costs
eriknw Oct 28, 2026
8523d29
Tensor: reshape in place past 2^31 on SuiteSparse 10.5.2
eriknw Oct 28, 2026
1de10d1
Tensor: reshape notes say 2^31, as the code does; drop a no-op resize…
eriknw Oct 28, 2026
9c97679
Tensor: size the GCXS export by its row pointer, and refuse a huge one
eriknw Nov 8, 2026
ddf9572
Tensor: make the JIT-only tests count in the pytest_jit job
eriknw Nov 8, 2026
99b31e9
Tensor: read a GCXS export back past 2^63 positions
eriknw Nov 8, 2026
c8b2d2e
Tensor: import a GCXS whose indptr is uint64
eriknw Nov 9, 2026
123808c
Tensor: take bool, integer and FP32 tensors into the FP64 TTM and MTT…
eriknw Oct 29, 2026
c507942
Tensor: say "pass shape=" when from_coo gets a shape where dtype goes
eriknw Oct 29, 2026
3acdf56
Tensor: name to_dense(fill_value=0) when np.asarray refuses a Tensor
eriknw Oct 29, 2026
7d5157c
Tensor: notes and user guide take in the SAPS pilot's findings
eriknw Oct 29, 2026
9982606
Tensor: ewise_mult's expansion refusal gives advice that works for ew…
eriknw Nov 8, 2026
78703bf
Tensor: select and apply take a 0-d Tensor as their scalar operand
eriknw Nov 8, 2026
2cc1b52
Tensor: drop the two flags that unify ignores from ewise_union
eriknw Nov 8, 2026
56d2d6e
Tensor: build the BOOL GCXS from arrays in the uint64 import test
eriknw Nov 10, 2026
b463f77
Tensor: permute float rows with any_second, which keeps NaN and -0.0
eriknw Nov 10, 2026
25b3bf5
Tensor: use any for a broadcast's diagonal product of floats, keeping…
eriknw Nov 10, 2026
e5dd7e6
Tensor: reduce through a selector with no identity seed, keeping NaN
eriknw Nov 10, 2026
9328f5c
Tensor: restore a test comment lost in an unrelated edit
eriknw Nov 10, 2026
51cdd42
Tensor: raise what Matrix raises for an index out of range
eriknw Nov 10, 2026
4bdddef
ai-notes: decisions 29-31, NaN and -0.0 against an identity, and inde…
eriknw Nov 10, 2026
faebfac
Tensor: let the NaN TTM test's numpy model make NaN from +inf and -inf
eriknw Nov 10, 2026
2850108
Ignore any_atan2 and any_pow in test_operator_types, made by Tensor t…
eriknw Nov 10, 2026
b7030fd
Ignore any_rpow in test_operator_types, made from the Tensor tests' a…
eriknw Nov 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ extend-ignore =
per-file-ignores =
benchmarks/*.py:B015,B018,
scripts/create_pickle.py:F403,F405,
scripts/tensor_bench/*.py:E402,
graphblas/tests/*.py:T201,B043,
graphblas/tests/test_tensor_oracles.py:T201,B043,B023,
graphblas/core/ss/matrix.py:SIM113,
graphblas/**/__init__.py:F401,
12 changes: 10 additions & 2 deletions .github/workflows/test_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,15 @@ jobs:
if: matrix.slowtask == 'notebooks'
timeout-minutes: 30
run: |
# Run notebooks only if numba is installed
# Run notebooks only if numba is installed. The Tensor notebooks need
# SuiteSparse:GraphBLAS 10 or later, which the version picker may not choose;
# without it, a Tensor raises NotImplementedError and they are skipped.
shopt -s extglob
if python -c 'import numba' 2> /dev/null ; then
jupyter nbconvert --to notebook --execute notebooks/*ipynb
if python -c 'import graphblas as gb; gb.Tensor(float, (1,))' 2> /dev/null ; then
jupyter nbconvert --to notebook --execute notebooks/*ipynb
else
echo "No Tensor with this SuiteSparse:GraphBLAS: skipping the Tensor notebooks"
jupyter nbconvert --to notebook --execute notebooks/!(Tensor*).ipynb
fi
fi
27 changes: 27 additions & 0 deletions ai-notes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# ai-notes

Curated notes for contributors, reviewers and developers of python-graphblas. They were written
with AI assistance and edited by the maintainers. They explain why the code is the way it is:
design, decisions, how it is verified and measured, and what is known to be missing. They are
not user documentation; that is in `docs/`.

Each topic has its own directory. Each page is meant to be readable on its own, without access
to anything outside this repository.

## tensor/: the experimental n-d `gb.Tensor`

| page | read it for |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tensor/design.md` | the data model (one Matrix plus a layout), copy-on-write views, the relayout planner and its cost model, how each operation family maps to SuiteSparse, the engines, and a map of the modules |
| `tensor/decisions.md` | the API and semantic decisions, with their reasons |
| `tensor/verification.md` | how correctness is checked: unit tests and how to run them without Numba or the JIT, independent randomized oracles (slow tests), cross-library fingerprints, real workloads, notebooks |
| `tensor/limitations-and-roadmap.md` | what is untested, missing or slow, and the planned order of work |
| `tensor/backport-candidates.md` | Tensor behavior that Matrix and Vector could adopt |
| `tensor/benchmarks.md` | results against pydata/sparse, scipy, torch, SPLATT, TACO and Finch, the real workloads, and how to rerun them (`scripts/tensor_bench/`) |
| `tensor/suitesparse-wishlist.md` | SuiteSparse:GraphBLAS features that would simplify or speed up the Tensor, in priority order, with evidence and proposed APIs |

The user guide's "Tensors" page (`docs/user_guide/tensor.rst`) covers how to use it.

Code comments may point at sections of these pages by their headings. If you change the
Tensor's design or a decision, update the matching page in the same pull request, and keep the
headings stable (or update the comments that cite them: `grep -rn "ai-notes" graphblas/`).
100 changes: 100 additions & 0 deletions ai-notes/tensor/backport-candidates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Tensor: backport candidates for Matrix and Vector

The Tensor is a new type, so it may go beyond Matrix and Vector behavior (`decisions.md`).
Where it does something Matrix and Vector could also do, this page lists it, so that the idea
is not lost and the two do not drift apart silently.

Each entry says what the Tensor does and what Matrix and Vector do today. "Today" was checked
by running python-graphblas on this branch, unless the entry says otherwise. Status:

- **on this branch**: the core code already exists here, in its own commit;
- **candidate**: not started.

## Candidates

1. **JIT C definitions for lifted ops between a scalar and an array or record UDT.**
- Tensor: the array-UDT TTM engine uses them; `plus_times[FP64, FP64[R]]` compiles to one
JIT kernel.
- Without them, such ops run SuiteSparse's generic path with a Numba cfunc per element.
- Status: **on this branch**, in core (`operator/udt_codegen.py`, `operator/binary.py`),
as its own change. Matrix and Vector get it too, and it can go to main separately.
2. **Conversions as methods:** `from_pydata_sparse`, `to_pydata_sparse`, `from_scipy_sparse`,
`to_scipy_sparse`.
- Tensor: methods.
- Matrix and Vector: only `graphblas.io` functions.
- Status: candidate.
3. **A nonzero pydata `fill_value` raises.**
- Tensor: raises ValueError, because a missing entry has no value.
- Matrix and Vector: `graphblas.io.from_pydata_sparse` drops it silently (COO, 1-d and
2-d), so the implicit values become missing.
- Status: candidate, low priority. Whether to warn or raise, and whether to offer an
opt-in, is undecided.
4. **`reduce(op, axis=..., keepdims=...)`** over any subset of axes.
- Matrix: `reduce_rowwise`, `reduce_columnwise` and `reduce_scalar`.
- Status: candidate, an `axis=` spelling on Matrix.
5. **`einsum` with any semiring.**
- Tensor: `gb.einsum`. It accepts Matrix and Vector operands, and the result is a Tensor.
- Matrix and Vector: none.
- Status: candidate, a form that returns a Matrix or Vector.
6. **`take` (modes raise, wrap and clip), `take_along_axis` and `vindex`.**
- Matrix and Vector: lists and ndarrays index as outer indices only.
- Status: candidate.
7. **An opt-in raise for negative indices** (`wraparound=False`).
- Matrix and Vector: negatives wrap once, with no option.
- Status: candidate, small.
8. **Infix operators return `NotImplemented` for operand types they do not know.**
- Tensor classes register in `utils._tensor_types`, and Matrix, Vector and Scalar defer to
them.
- For any other type, Matrix and Vector raise TypeError, so a third-party type's reflected
operator never runs (checked: `A + Foo()` raises even when `Foo` defines `__radd__`).
- Status: candidate. The design question is which types to defer to.
9. **Zero-copy Container load and unload, and an O(1) orientation flip.**
- Tensor: used throughout `tensor_layout.py` (`_Unloaded`, `_VectorArray`,
`flip_orientation`, `matrix_from_arrays`).
- Matrix: `ss.unpack` widens 32-bit indices to 64-bit, and `ss.export` copies.
- Status: candidate.
10. **Generated Numba kernels with a verified disk cache.**
- Tensor: `tensor_numba._compile` writes a file per source hash and runs it only if its
bytes match the generated source.
- Matrix and Vector: Numba UDFs compile in every process.
- Status: candidate, if other generated code appears.
11. **Not retrying after a failed compile.**
- Tensor: the array-UDT engine leaves SuiteSparse's `"load"`, warns once, and turns
itself off. (It used to restore the setting; with `"run"` back, auto-lift raised it to
`"on"` again and the next UDT operation retried the compile and raised.)
- UDT auto-lift leaves `"load"` in place after a failure too.
- Status: now the same policy in both; a warning from auto-lift as well is a
candidate.
12. **Lifted UDT operators without Numba when the JIT is on.**
- Tensor: the engine makes its operators with `GxB_BinaryOp_new`, a NULL function pointer
and the generated C definition.
- Matrix and Vector: lifted operators are Numba cfuncs, with a C definition attached for
the JIT.
- Status: candidate. UDT operators would then work without Numba.
13. **Deterministic JIT C names for anonymous UDTs.**
- Tensor: fixed names (`_gbtensor_fp64x16`).
- Matrix and Vector: `_gbudt_N`, in registration order, so processes overwrite each
other's cached JIT kernels.
- Status: candidate, a name from a hash of the dtype.
14. **numpy-style `reshape`, `ravel` and `flatten`.**
- Tensor: `reshape(..., copy=None)`, a view where the layout allows.
- Matrix and Vector: no such methods (checked), only `M.ss.reshape`.
- Status: candidate.
15. **Doctests of the user-guide page.**
- Tensor: `test_user_guide_examples` runs every example of `docs/user_guide/tensor.rst`.
- The other user-guide pages are not doctested.
- Status: candidate (testing).
16. **`isequal` and `isclose` across kinds.**
- Tensor: `T.isequal(A)` accepts a Matrix, Vector or Scalar of the same shape.
- Matrix and Vector: `A.isequal(T)` defers to the Tensor, but a Matrix and a Vector (or
a Scalar) still cannot be compared with each other: `A.isequal(v)` raises TypeError.
- Status: candidate, for comparisons between Matrix, Vector and Scalar.

## Already the same, nothing to backport

- Broadcasting a Vector across a Matrix in element-wise ops: `A * v` multiplies column `j` by
`v[j]`, numpy-style, as the Tensor does.
- A GraphBLAS Scalar as an index (`A[s, :]`, `v[s]`).
- Deleting a region (`del A[0:2, :]`).

Masks that combine a Tensor with a Matrix or Vector are Tensor-only: they make a Tensor mask.
Loading
Loading