- (specialized-array-reshape array new-domain [ copy-on-failure? #f ])procedure
Assumes that array is a specialized array, new-domain is an interval with the same volume as (array-domain array), and copy-on-failure?, if given, is a boolean.
If there is an affine map that takes the multi-indices in new-domain to the cells in (array-body array) storing the elements of array in lexicographical order, returns a new specialized array, with the same body and elements as array and domain new-domain. The result inherits its mutability and safety from array.
If there is not an affine map that takes the multi-indices in new-domain to the cells storing the elements of array in lexicographical order and copy-on-failure? is #t, then returns a specialized array copy of array with domain new-domain, storage class (array-storage-class array), mutability (mutable-array? array), and safety (array-safe? array).
It is an error if these conditions on the arguments are not met.
Note: The code in the sample implementation to determine whether there exists an affine map from new-domain to the multi-indices of the elements of array in lexicographical order is modeled on the corresponding code in the Python library NumPy.
Note: In the sample implementation, if an array cannot be reshaped and copy-on-failure? is #f, an error is raised in tail position. An implementation might want to replace this error call with a continuable exception to give the programmer more flexibility.
Examples: Reshaping an array is not a Bawden-type array transform. For example, we use array-display defined below to see:
;;; The entries of A are the multi-indices of the locations (define A (array-copy (make-array (make-interval '#(3 4)) list))) (array-display A) ;;; Displays ;;; (0 0) (0 1) (0 2) (0 3) ;;; (1 0) (1 1) (1 2) (1 3) ;;; (2 0) (2 1) (2 2) (2 3) (array-display (array-rotate A 1)) ;;; Displays ;;; (0 0) (1 0) (2 0) ;;; (0 1) (1 1) (2 1) ;;; (0 2) (1 2) (2 2) ;;; (0 3) (1 3) (2 3) (array-display (specialized-array-reshape A (make-interval '#(4 3)))) ;;; Displays ;;; (0 0) (0 1) (0 2) ;;; (0 3) (1 0) (1 1) ;;; (1 2) (1 3) (2 0) ;;; (2 1) (2 2) (2 3) (define B (array-sample A '#(2 1))) (array-display B) ;;; Displays ;;; (0 0) (0 1) (0 2) (0 3) ;;; (2 0) (2 1) (2 2) (2 3) (array-display (specialized-array-reshape B (make-interval '#(8)))) => fails (array-display (specialized-array-reshape B (make-interval '#(8)) #t)) ;;; Displays ;;; (0 0) (0 1) (0 2) (0 3) (2 0) (2 1) (2 2) (2 3)
The following examples succeed:
(specialized-array-reshape (array-copy (make-array (make-interval '#(2 1 3 1)) list)) (make-interval '#(6))) (specialized-array-reshape (array-copy (make-array (make-interval '#(2 1 3 1)) list)) (make-interval '#(3 2))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list))) (make-interval '#(6))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list))) (make-interval '#(3 2))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#f #f #f #t)) (make-interval '#(3 2))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#f #f #f #t)) (make-interval '#(3 1 2 1))) (specialized-array-reshape (array-sample (array-reverse (array-copy (make-array (make-interval '#(2 1 4 1)) list)) '#(#f #f #f #t)) '#(1 1 2 1)) (make-interval '#(4))) (specialized-array-reshape (array-sample (array-reverse (array-copy (make-array (make-interval '#(2 1 4 1)) list)) '#(#t #f #t #t)) '#(1 1 2 1)) (make-interval '#(4)))
The following examples raise an exception:
(specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#t #f #f #f)) (make-interval '#(6))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#t #f #f #f)) (make-interval '#(3 2))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#f #f #t #f)) (make-interval '#(6))) (specialized-array-reshape (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#f #f #t #t)) (make-interval '#(3 2))) (specialized-array-reshape (array-sample (array-reverse (array-copy (make-array (make-interval '#(2 1 3 1)) list)) '#(#f #f #f #t)) '#(1 1 2 1)) (make-interval '#(4)) ) (specialized-array-reshape (array-sample (array-reverse (array-copy (make-array (make-interval '#(2 1 4 1)) list)) '#(#f #f #t #t)) '#(1 1 2 1)) (make-interval '#(4)))
In the next examples, we start with vector fields, $100\times 100$ arrays of 4-vectors. In one example, we reshape each large array to $100\times 100\times2\times2$ vector fields (so we consider each 4-vector as a $2\times 2$ matrix), and multiply the $2\times 2$ matrices together. In the second example, we reshape each 4-vector to a $2\times 2$ matrix individually, and compare the times.
(define interval-flat (make-interval '#(100 100 4))) (define interval-2x2 (make-interval '#(100 100 2 2))) (define A (array-copy (make-array interval-flat (lambda args (random-integer 5))))) (define B (array-copy (make-array interval-flat (lambda args (random-integer 5))))) (define C (array-copy (make-array interval-flat (lambda args 0)))) (define (2x2-matrix-multiply-into! A B C) (let ((C! (array-setter C)) (A_ (array-getter A)) (B_ (array-getter B))) (C! (+ (* (A_ 0 0) (B_ 0 0)) (* (A_ 0 1) (B_ 1 0))) 0 0) (C! (+ (* (A_ 0 0) (B_ 0 1)) (* (A_ 0 1) (B_ 1 1))) 0 1) (C! (+ (* (A_ 1 0) (B_ 0 0)) (* (A_ 1 1) (B_ 1 0))) 1 0) (C! (+ (* (A_ 1 0) (B_ 0 1)) (* (A_ 1 1) (B_ 1 1))) 1 1))) ;;; Reshape A, B, and C to change all the 4-vectors to 2x2 matrices (time (array-for-each 2x2-matrix-multiply-into! (array-curry (specialized-array-reshape A interval-2x2) 2) (array-curry (specialized-array-reshape B interval-2x2) 2) (array-curry (specialized-array-reshape C interval-2x2) 2))) ;;; Displays ;;; 0.015186 secs real time ;;; 0.015186 secs cpu time (0.015186 user, 0.000000 system) ;;; 4 collections accounting for 0.004735 secs real time (0.004732 user, 0.000000 system) ;;; 46089024 bytes allocated ;;; no minor faults ;;; no major faults ;;; Reshape each 4-vector to a 2x2 matrix individually (time (array-for-each (lambda (A B C) (2x2-matrix-multiply-into! (specialized-array-reshape A (make-interval '#(2 2))) (specialized-array-reshape B (make-interval '#(2 2))) (specialized-array-reshape C (make-interval '#(2 2))))) (array-curry A 1) (array-curry B 1) (array-curry C 1))) ;;; Displays ;;; 0.039193 secs real time ;;; 0.039193 secs cpu time (0.039191 user, 0.000002 system) ;;; 6 collections accounting for 0.006855 secs real time (0.006851 user, 0.000001 system) ;;; 71043024 bytes allocated ;;; no minor faults ;;; no major faults