Some consequences of zero-dimensional arrays. Bradley Lucier 14 Jun 2022 17:05 UTC

With array-curry, if the dimension of the whole array is dim, then (a)
if right-dimension is dim, then the entire array is wrapped in a
zero-dimensional array, and (b) if right-dimension is zero, then each
element is wrapped in a zero-dimensional array (each time it's accessed).

This shows up in the array-squeeze example,

 > (load "generic-arrays.scm")
"/home/lucier/lang/scheme/srfi-231/srfi-231/generic-arrays.scm"
 > (define a (make-specialized-array (make-interval '#(1 1 1))
generic-storage-class 42))
 > (define (array-squeeze a)
   (call-with-values
       (lambda ()
         (let ((interval (array-domain a)))
           (partition (lambda (k)
                        (eqv? (interval-width interval k) 1))
                      (iota (array-dimension a)))))
     (lambda (ones rest)
       (car (array->list
             (array-curry                           ;; this array has
exactly one element
              (array-permute
               a (list->vector (append ones rest))) ;; put all
length-one axes at beginning
              (length rest)))))))
 > (array-squeeze a)
#<%%array #30
           domain: #<%%interval #31
                      dimension: 0
                      %%volume: 1
                      lower-bounds: #()
                      upper-bounds: #()>
           getter: #<procedure #32>
           setter: #<procedure #33>
           storage-class:
            #<storage-class #6
               getter: #<procedure #7>
               setter: #<procedure #8>
               checker: #<procedure #9>
               maker: #<procedure #10 make-vector>
               copier: #<procedure #11 vector-copy!>
               length: #<procedure #12 vector-length>
               default: #f
               data?: #<procedure #13>
               data->body: #<procedure #14>>
           body: #(42)
           indexer: #<procedure #34>
           safe?: #f
           in-order?: #t>

It also comes up in array-inner-product:

 > (define a (list*->array 1 '(1 1 1 1)))
 > (define b (list*->array 1 '(1 2 3 4)))
 > (array-copy (array-inner-product a + * b))
 > (array-copy (array-inner-product a + * b))
#<%%array #38
           domain: #<%%interval #39
                      dimension: 0
                      %%volume: 1
                      lower-bounds: #()
                      upper-bounds: #()>
           getter: #<procedure #40>
           setter: #<procedure #41>
           storage-class:
            #<storage-class #6
               getter: #<procedure #7>
               setter: #<procedure #8>
               checker: #<procedure #9>
               maker: #<procedure #10 make-vector>
               copier: #<procedure #11 vector-copy!>
               length: #<procedure #12 vector-length>
               default: #f
               data?: #<procedure #13>
               data->body: #<procedure #14>>
           body: #(10)
           indexer: #<procedure #42>
           safe?: #f
           in-order?: #t>

This is one of the reasons that (index-rotate n k) now allows k = n, as
the fourth argument of array-inner-product needs to be rotated by 1
before both arrays are curried with right-dimension = 1 before reduction
(which is where the zero-dimensional arrays come in).  So now this works
when a and b are one-dimensional arrays.

And now we have zero-dimensional permutations, translations, etc.

Brad