6 Arrays
On this page:
top
up

6.3BroadcastingπŸ”— i

It is often useful to apply a pointwise operation to two or more arrays in a many-to-one manner. Library support for this, which math/array provides, is called broadcasting.

Creating a 6×6 identity matrix:
> (define diag(diagonal-array 2610))
> (array-shape diag)

- : Indexes

'#(6 6)

> diag

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes (U One Zero)))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[1 0 0 0 0 0]

#[0 1 0 0 0 0]

#[0 0 1 0 0 0]

#[0 0 0 1 0 0]

#[0 0 0 0 1 0]

#[0 0 0 0 0 1]])

Multiplying each element by 10:
> (array-shape (array 10))

- : Indexes

'#()

> (array* diag(array 10))

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes Index))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[10 0 0 0 0 0]

#[0 10 0 0 0 0]

#[0 0 10 0 0 0]

#[0 0 0 10 0 0]

#[0 0 0 0 10 0]

#[0 0 0 0 0 10]])

Adding (array #[012345]) pointwise to every row:
> (array+ (array* diag(array 10))
(array #[012345]))

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes Nonnegative-Fixnum))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[10 1 2 3 4 5]

#[0 11 2 3 4 5]

#[0 1 12 3 4 5]

#[0 1 2 13 4 5]

#[0 1 2 3 14 5]

#[0 1 2 3 4 15]])

6.3.1Broadcasting RulesπŸ”— i

Suppose we have two array shapes ds= (vector d0d1... ) and es= (vector e0e1... ). Broadcasting proceeds as follows:
  1. The shorter shape is padded on the left with 1 until it is the same length as the longer shape.

  2. For each axis k, dk and ek are compared. If dk= ek, the result axis is dk; if one axis is length 1, the result axis is the length of the other; otherwise fail.

  3. Both arrays’ axes are stretched by (conceptually) copying the rows of axes with length 1.

Example: Suppose we have an array drr with shape ds= #(413) and another array err with shape es= #(33). Following the rules:
  1. es is padded to get #(133).

  2. The result axis is derived from #(413) and #(133) to get #(433).

  3. drr’s second axis is stretched to length 3, and err’s new first axis (which is length 1 by rule 1) is stretched to length 4.

The same example, but more concrete:
> (define drr
(array #[#[#["00""01""02"]]
#[#["10""11""12"]]
#[#["20""21""22"]]
#[#["30""31""32"]]]))
> (array-shape drr)

- : Indexes

'#(4 1 3)

> (define err
(array #[#["aa""ab""ac"]
#["ba""bb""bc"]
#["ca""cb""cc"]]))
> (array-shape err)

- : Indexes

'#(3 3)

> (define drr+err(array-map string-append drrerr))
> (array-shape drr+err)

- : Indexes

'#(4 3 3)

> drr+err

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[#["00aa" "01ab" "02ac"]

#["00ba" "01bb" "02bc"]

#["00ca" "01cb" "02cc"]]

#[#["10aa" "11ab" "12ac"]

#["10ba" "11bb" "12bc"]

#["10ca" "11cb" "12cc"]]

#[#["20aa" "21ab" "22ac"]

#["20ba" "21bb" "22bc"]

#["20ca" "21cb" "22cc"]]

#[#["30aa" "31ab" "32ac"]

#["30ba" "31bb" "32bc"]

#["30ca" "31cb" "32cc"]]])

Notice how the row #["00""01""02"] in drr is repeated in the result because drr’s second axis was stretched during broadcasting. Also, the column #[#["aa"]#["ba"]#["ca"]] in err is repeated because err’s first axis was stretched.

For the above example, array-map does this before operating on drr and err:
> ds

- : Indexes

'#(4 3 3)

> (array-broadcast drrds)

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[#["00" "01" "02"]

#["00" "01" "02"]

#["00" "01" "02"]]

#[#["10" "11" "12"]

#["10" "11" "12"]

#["10" "11" "12"]]

#[#["20" "21" "22"]

#["20" "21" "22"]

#["20" "21" "22"]]

#[#["30" "31" "32"]

#["30" "31" "32"]

#["30" "31" "32"]]])

> (array-broadcast errds)

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array

#[#[#["aa" "ab" "ac"]

#["ba" "bb" "bc"]

#["ca" "cb" "cc"]]

#[#["aa" "ab" "ac"]

#["ba" "bb" "bc"]

#["ca" "cb" "cc"]]

#[#["aa" "ab" "ac"]

#["ba" "bb" "bc"]

#["ca" "cb" "cc"]]

#[#["aa" "ab" "ac"]

#["ba" "bb" "bc"]

#["ca" "cb" "cc"]]])

6.3.2Broadcasting ControlπŸ”— i

The parameter array-broadcasting controls how pointwise operations broadcast arrays. Its default value is #t, which means that broadcasting proceeds as described in Broadcasting Rules. Another possible value is #f, which allows pointwise operations to succeed only if array shapes match exactly:

array-shape-broadcast: incompatible array shapes

(array-broadcasting #f): '#(3 3), '#()

Another option is R-style permissive broadcasting, which allows pointwise operations to always succeed, by repeating shorter axes’ rows instead of repeating just singleton axes’ rows:
> arr10

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array #["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"])

> arr3

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array #["0" "1" "2"])

> (array-map string-append arr10(array #["+""-"])arr3)

array-shape-broadcast: incompatible array shapes

(array-broadcasting #t): '#(10), '#(2), '#(3)

> (parameterize ([array-broadcasting 'permissive])
(array-map string-append arr10(array #["+""-"])arr3))

- : #(struct:Array

(Indexes Index (Boxof Boolean) (-> Void) (-> Indexes String))

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:56:13 prop:equal+hash>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:55:13 prop:custom-write>

#<syntax:build/user/8.18/pkgs/math-lib/math/private/array/typed-array-struct.rkt:54:13 prop:custom-print-quotable>)

(array #["0+0" "1-1" "2+2" "3-0" "4+1" "5-2" "6+0" "7-1" "8+2" "9-0"])

Notice that (array #["+""-"]) was repeated five times, and that arr3 was repeated three full times and once partially.

top
up

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /