Numpy's array manipulation routines compared to this SRFI. Bradley Lucier (25 Feb 2022 20:17 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Alex Shinn
(28 Aug 2024 13:09 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Bradley Lucier
(28 Aug 2024 18:10 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Bradley Lucier
(29 Aug 2024 00:16 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Alex Shinn
(29 Aug 2024 13:49 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Bradley Lucier
(30 Aug 2024 00:15 UTC)
|
Re: Numpy's array manipulation routines compared to this SRFI.
Alex Shinn
(30 Aug 2024 08:05 UTC)
|
Summary: Most array manipulation routines in NumPy have associated methods in this SRFI. Maybe this SRFI should have array-block, an inverse to array-tile. (A use case for array-tile is segmenting a large array to pass to GPU memory blocks, so array-block could copy the contents of those blocks back to a single array.) array-squeeze combines existing things in a simple way. I invite anyone interested in having NumPy's array manipulation power in Scheme to review this list. Also, the array-block example uses a lot of list*->arrays, it might inform opinions about the proper argument order. Brad Numpy array manipulation routines, from https://numpy.org/doc/stable/reference/routines.array-manipulation.html We note approximate correspondences with this SRFI. Numpy operations allow the user to consider either C or Fortran ordering; in this SRFI one can do something like that, search for "fortran" below. numpy.copyto: Like array-assign! numpy.shape: Like array-domain numpy.reshape: Like specialized-array-reshape numpy.ravel: Like specialized-array-reshape with a copy if necessary. ndarray.flat: Seems like what a SRFI 42 :array iterator would be like. ndarray.flatten: (specialized-array-reshape (array-copy ...)) numpy.moveaxis: array-permute numpy.rollaxis: says to use numpy.moveaxis numpy.swapaxes: array-permute numpy.ndarray.T: array-permute numpy.transpose: array-permute (Documentation says "A view is returned whenever possible." When wouldn't it be possible?) numpy.atleast_1d: ??? numpy.atleast_2d: ??? numpy.atleast_3d: ??? numpy.broadcast: ??? numpy.broadcast_to: ??? numpy.broadcast_arrays: ??? numpy.expand_dims: ??? numpy.squeeze: easy to write with array-permute and array-curry, but because this SRFI does not have zero-dimensional arrays has different semantics in case all axes have length one. (By the way, numpy is not consistent in its handling of zero-dimensional arrays, there are quite a number of exceptional cases.) (define (array-squeeze a) (let* ((domain (array-domain a)) (dim (interval-dimension domain)) (all-axes (iota dim)) (ks ;; indices of all the length-one axes (filter (lambda (k) (= (- (interval-upper-bound domain k) (interval-lower-bound domain k)) 1)) all-axes)) (length-ks (length ks)) (permutation ;; put length-one axes first, leave the rest in order. (list->vector (append ks (remove (lambda (k) (memv k ks)) all-axes))))) (cond ((zero? length-ks) a) ((= dim length-ks) ;; a has one element, Numpy returns a zero-dimensional array containing the element. (car (array->list a))) (else (car (array->list (array-curry ;; this array has only one element. (array-permute a permutation) (- dim (length ks))))))))) numpy.asarray: I don't understand it completely, but it appears that list->array, list*->array, vector->array, and vector*->array, as well as, e.g. (array-copy (array-map inexact a) f64-storage-class) covers most of the bases. numpy.asanyarray: Similar to numpy.asarray, I think. numpy.asmatrix: It seems that matrices and arrays are separate numpy.asfarray: Use (array-copy (array-map inexact a) f64-storage-class) numpy.asfortranarray: If you want to take the same elements and go through them in Fortran order you could (assuming the elements of a are contiguous and in order in its body) (define (array->fortran a) (let* ((domain (array-domain a)) (dim (interval-dimension domain)) (reverse-permutation (list->vector (reverse (iota dim)))) (reverse-domain (interval-permute domain reverse-permutation))) (array-permute (specialized-array-reshape a reverse-domain) reverse-permutation))) Then > (define b (specialized-array-reshape (make-specialized-array-from-data (list->vector (iota 10))) (make-interval '#(2 5)))) > (array->vector* b) #(#(0 1 2 3 4) #(5 6 7 8 9)) > (array->vector* (array->fortran b)) #(#(0 2 4 6 8) #(1 3 5 7 9)) > (array-body b) #(0 1 2 3 4 5 6 7 8 9) > (array-body (array->fortran b)) #(0 1 2 3 4 5 6 7 8 9) numpy.ascontiguousarray: I don't quite understand what this does, but array-map, array-copy, and specialized-array-reshape seems to do it. numpy.asarray_chkfinite: Like numpy.asarray, but throws an error if any element is inexact and not finite. numpy.asscalar: Use the above array-squeeze with all dimensions length 1. numpy.require: Seems like combining numpy.asarray, numpy.asfarray, etc. numpy.concatenate: array-append numpy.stack: array-stack numpy.block: Interesting, inverse to array-tile in this SRFI, in a similar way that array-stack is a partial inverse to array-curry after array-permute. Something like > (define (array-block list*) (define (helper axis list-or-array) (if (list? list-or-array) (apply array-append axis (map (lambda (l-or-a) (helper (+ axis 1) l-or-a)) list-or-array)) list-or-array)) (helper 0 list*)) > (define a (array-block (list (list (list*->array '((0 1) (2 3)) 2) (list*->array '((4 5) (6 7)) 2)) (list (list*->array '((8 9)) 2) (list*->array '((10 11)) 2))))) > (array->vector* a) #(#(0 1 4 5) #(2 3 6 7) #(8 9 10 11)) Maybe this SRFI should have something like this. Only instead of nested lists/nested vectors/... the argument should be an array of arrays, like the output of array-tile. numpy.vstack, numpy.hstack, numpy.dstack, numpy.column_stack, numpy.row_stack: array-stack numpy.split, numpy.array_split, numpy.dsplit, numpy.hsplit, numpy.vsplit: array-tile numpy.tile: nada numpy.repeat: nada numpy.delete: Like the example in the SRFI document after array-stack. numpy.insert: Combine array-permute, array-curry, array->list, array-stack. numpy.append: array-append. numpy.resize: shouldn't exist. numpy.trim_zeros: Nada numpy.uniq: combine array->list, sort, uniq, list->array. numpy.flip, numpy.fliplr, numpy.flipud: array-reverse numpy.reshaps: specialized-array-reshape numpy.roll: combine array-curry, array->list, take and drop from SRFI 1, append, array-stack; see the example in the SRFI document after array-stack. numpy.rot90: combine array-permute and array-reverse (I think).