On this page:
6.3.1 Broadcasting Rules
6.3.2 Broadcasting Control

6.3 Broadcasting

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 2 6 1 0))
> (array-shape diag)

eval:20:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: diag12

  in: diag

> diag

eval:21:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: diag12

  in: diag

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

- : Indexes

'#()

> (array* diag (array 10))

eval:23:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: diag12

  in: 10

Adding (array #[0 1 2 3 4 5]) pointwise to every row:
> (array+ (array* diag (array 10))
          (array #[0 1 2 3 4 5]))

eval:24:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: diag12

  in: #(0 1 2 3 4 5)

6.3.1 Broadcasting Rules

Suppose we have two array shapes ds = (vector d0 d1 ...) and es = (vector e0 e1 ...). 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 = #(4 1 3) and another array err with shape es = #(3 3). Following the rules:
  1. es is padded to get #(1 3 3).

  2. The result axis is derived from #(4 1 3) and #(1 3 3) to get #(4 3 3).

  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)

eval:26:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: drr13

  in: drr

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

eval:28:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: err14

  in: err

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

eval:29:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: drr13

  in: err

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:29:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: err14

  in: err

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

> (array-shape drr+err)

eval:30:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: drr+err

  in: drr+err

> drr+err

eval:31:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: drr+err

  in: drr+err

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:
> (define ds (array-shape-broadcast (list (array-shape drr)
                                          (array-shape err))))

eval:32:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: drr13

  in: err

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:32:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: err14

  in: err

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

> ds

eval:33:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: ds

  in: ds

> (array-broadcast drr ds)

eval:34:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: drr13

  in: ds

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:34:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: ds

  in: ds

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

> (array-broadcast err ds)

eval:35:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: err14

  in: ds

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:35:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: ds

  in: ds

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

6.3.2 Broadcasting Control

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:
> (parameterize ([array-broadcasting #f])
    (array* (index-array #(3 3)) (array 10)))

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:
> (define arr10 (array-map number->string (index-array #(10))))
> (define arr3 (array-map number->string (index-array #(3))))
> arr10

eval:39:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: arr1017

  in: arr10

> arr3

eval:40:0: Type Checker: missing type for top-level

identifier;

 either undefined or missing a type annotation

  identifier: arr318

  in: arr3

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

eval:41:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: arr1017

  in: arr3

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:41:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: arr318

  in: arr3

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

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

eval:42:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: arr1017

  in: arr3

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

eval:42:0: Type Checker: missing type for top-level identifier;

 either undefined or missing a type annotation

  identifier: arr318

  in: arr3

  context...:

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/utils/tc-utils.rkt:123:0: report-all-errors

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:515:0: tc-toplevel-form

   fail-to-succeed

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/tc-setup.rkt:39:0: tc-setup

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/typed-racket-lib/typed-racket/typed-racket.rkt:24:4

   /Users/mflatt/build/macro/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization

   /Users/mflatt/build/macro/build/user/6.2.900.4/pkgs/sandbox-lib/racket/sandbox.rkt:837:5: loop

Type Checker: Summary: 2 errors encountered

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