First stab at API for adding new array axes and broadcasting arrays
Bradley Lucier 17 Sep 2025 02:43 UTC
I was stuck on several questions:
1. What notation wouldn't be too onerous to specify adding new axes?
2. What to do with array broadcasting when an axis has a nonzero lower
bound?
3. Should array broadcasting be implicit, and tied to an immediate
"consumption" of the broadcast arrays by an operation, or be explicit,
returning new arrays that could be used any number of times? Or have both?
It also became clear to me that broadcasting without the ability to add
new axes, or being able to add axes only at the left and using
array-permute to put them elsewhere, is not reasonable.
Here's my first attempt at dealing with these issues. I'm not hung up
on the particulars of any of this.
Brad
(array<-scalar obj)
Returns (make-array (make-interval '#()) (lambda () obj)). (People seem
to like treating scalars like arrays, so let's make it easier to do so.)
(array-add-axes array vector)
Sample calls:
(array-add-axes A '#(* 0 1 * 2 * 3))
(array-add-axes A (vector '* 0 1 '* 2 '* 3))
(array-add-axes A '#(* * *)) ;; if A is zero-dimensional
Assumes that the first argument A is an array with dimension d.
Assumes the second argument is a vector v whose elements are the exact
integers 0, 1, ..., d-1, in order, interspersed with zero or more
instances of the symbol *.
Returns a new array A* that shares its elements with A in the same
lexicographical order.
Any entry in v with a nonnegative integer j entry denotes an axis in the
domain of A* with the same lower and upper bounds as the j'th axis of
domain of A.
Any entry in v with the symbol * denotes a new axis in the domain of A*
with lower bound 0 and upper bound 1.
(array-broadcast list-of-As)
Assumes that list-of-As is a nonempty list of immutable arrays.
Let D be the maximum of the dimensions of the arrays in list-of-As.
A new list of arrays, list-of-A*s, is constructed by adding axes to the
left of existing axes of the arrays in list-of-As with array-add-axes so
that all arrays in list-of-A*s have dimension D.
The arrays in list-of-A*s are now required to have the following
properties, checked in order:
1. If the domain of any A* in list-of-A*s has an axis j with nonzero
lower bound, then the domains of all arrays A* in list-of-A*s must have
the same lower and upper bounds for axis j.
2. If the domain of any A* in list-of-A*s has an axis j with an
upper-bound u_j different from 1, then axis j in the domain of all
arrays A* in list-of-A*s must have either upper bound u_j or upper bound 1.
We then use the usual broadcast rules (which we have not yet specified
here) to form a new list-of-A**s containing arrays A** all with the same
domain.