This week, I finished the compile-time check validity of coiteration in the PR [ENH] Check validity of coiteration. This has a few hacks, but it works and is able to raise a compiler-error when co-iteration with a disjunctive merge with an unordered level is involved.
I am starting to understand the merge lattice class more. It is simply another abstraction on iteration that now iterates over collections of tensors instead of collections of levels like co-iteration does.
As a few pre-steps towards implementing the merge lattice, I also added a PR that adds compile-time checks for valid methods to be defined for any container traits that would store indices in the sparse tensor, or the pointers to the next level (or data array): Adding required member functions of abstract container traits. This tightens up the API to allow users to define their own custom containers as long as they implement a certain API.
I also started working on the Tensor class implementation. The tensor class now connects a collection of levels to actual data and represents a sparse n-dimensional array. [ENH] Adding Tensor implementation. This probably will take up most of my next week, since I will need to understand how to implement the iterator over the tensor. This will require initializing iterators over all the levels that define the tensor and then also dereferencing to get the right indices and data.
A few questions I’ll have to figure out this week are:
-
How to initialize the iterators of each level?
-
How to design the Tensor’s iterator? Should I follow a design similar to `Coiterate` since they are both at a high-level iterating over a collection of levels?
-
What should dereference do? My thinking is return a tuple of indices (i.e. IKs) and then the data value, which is just the PK pointer into the data vector.
I.e. tensor* -> (1, 0, 5) 60.3 returns the value at index (1, 0, 5) in the 3D sparse array with non-zero value 60.3 there. -
Does it matter if we iterate over an unordered level?