Should array-tile be generalized? Comparing to NumPy. Bradley Lucier (12 Mar 2022 20:28 UTC)

Should array-tile be generalized? Comparing to NumPy. Bradley Lucier 12 Mar 2022 20:28 UTC

I just added to my own repository an implementation of array-block:

https://github.com/gambiteer/srfi-231/commit/c1dcce0c094fbbbd092c8ed3d61bf6ea40236d7d

which corresponds to numpy.block in NumPy:

https://numpy.org/doc/stable/reference/generated/numpy.block.html

I've started to add documentation for it, and the short description is

                ": Assumes that an array has been decomposed into blocks
by cuts perpendicular to each coordinate axis; takes an array of those
blocks as arguments, and returns a reconstructed array.  A more general
inverse to "(<a> href:'#array-tile (<code>'array-tile))".")

I say that it's more general than just an inverse to array-tile, because
array-tile breaks an array into subarrays all of whose domains have the
same "widths" except possibly for the subarrays with the highest indices
in case the given widths do not divide evenly the "widths" of the
original array.  (I've added interval-width and interval-widths to my
own repository, too.)  array-block reconstructs an array from subblocks
no matter their widths, as long as they arise from cuts perpendicular to
axes and they fit together.  (No Jenga towers allowed.)

Python has numpy.array_split

https://numpy.org/doc/stable/reference/generated/numpy.array_split.html

and numpy.split

https://numpy.org/doc/stable/reference/generated/numpy.split.html

Each of these cuts the array perpendicular to a single axis, so is less
general than array-tile here, but allows specifying the distance between
each cut separately, which is more general than array-tile.

I'm thinking of the situation where one has a block diagonal matrix with
blocks of different sizes (view the following in a fixed-width font):

|-----------------------|
|               | |     |
|               | |     |
|               | |     |
|       X       | |     |
|               | |     |
|               | |     |
|-----------------------|
|               |X|     |
|-----------------------|
|               | |     |
|               | |  X  |
|               | |     |
|-----------------------|

where typically the blocks marked by an X are nonzero and the other
blocks are zero.

Given a 2D array of blocks of these shapes, array-block can reconstruct
the original matrix, but there is no routine that takes as an argument
the large matrix and returns a matrix as subblocks.

To test array-block, I had to basically write something that decomposed
arrays in this way, to see whether array-block would put them back
together correctly.

so I"m thinking that array-tile could be generalized to

(array-tile array S)

where now the k'th entry in S is either a positive exact integer (as it
is now), or a vector of positive exact integers whose sum is

(interval-width (array-domain A) k)

If it's an integer S_k, then the array is subdivided in the k'th
direction into blocks all of width S_k, except possibly the last block
if the array width in that axis is not a multiple of S_k.

And if the k'th entry is a vector of positive integers that sum to the
width in that direction, then the original array is cut in that
direction into slices with those widths.

And now that I've written all that, I think the answer is "yes", unless
people think that adds too much complexity.

Brad