Skip to content

Commit

Permalink
Add Julia Base Broadcast background
Browse files Browse the repository at this point in the history
  • Loading branch information
charleskawczynski committed Jan 27, 2025
1 parent 72e3627 commit 9b7afa9
Showing 1 changed file with 89 additions and 4 deletions.
93 changes: 89 additions & 4 deletions docs/src/broadcast_background.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,96 @@
# Julia Base Broadcast Background

Please see the official Julia [broadcasting documentation]
Here, we'll provide our own brief background of Julia Base's broadcast
machinery. Please see the official Julia [broadcasting documentation]
(https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting), for more
information.

Here, we'll give a brief background of Julia Base's broadcast machinery.
## Introduction

## From parse time to runtime
Sometimes, you need to perform operations on arrays of different sizes, like
adding a vector to each column of a matrix. One inefficient approach would be
to expand the vector to match the matrix size:

```julia
julia> a = rand(2, 1); A = rand(2, 3);

julia> repeat(a, 1, 3) + A
2×3 Array{Float64,2}:
1.20813 1.82068 1.25387
1.56851 1.86401 1.67846
```

This can be inefficient with large arrays, so Julia offers the broadcast
function. It automatically expands smaller dimensions in the arrays to match
the larger ones without using extra memory and applies the operation element by
element:

```julia
julia> broadcast(+, a, A)
2×3 Array{Float64,2}:
1.20813 1.82068 1.25387
1.56851 1.86401 1.67846

julia> b = rand(1,2)
1×2 Array{Float64,2}:
0.867535 0.00457906

julia> broadcast(+, a, b)
2×2 Array{Float64,2}:
1.71056 0.847604
1.73659 0.873631
```

Operators like `.+` and `.*` are shorthand for broadcast calls (with the added
benefit of "fusing" the operations). The `broadcast!` function lets you specify
where to store the result (and you can use `.=` to do this in a similar fused
way). For example, `f.(args...)` is the same as `broadcast(f, args...)`,
offering a simpler syntax for broadcasting any function. Also, nested "dot
calls" like `f.(...)` automatically fuse into a single broadcast call.

Broadcasting isn't limited to arrays — it also works with scalars, tuples, and
other collections. By default, only certain types are treated as scalars, such
as `Number`s, `String`s, `Symbol`s, `Type`s, `Function`s, and common singletons
like `missing` and `nothing`. Other types are treated element by element.

```julia
julia> convert.(Float32, [1, 2])
2-element Vector{Float32}:
1.0
2.0

julia> ceil.(UInt8, [1.2 3.4; 5.6 6.7])
2×2 Matrix{UInt8}:
0x02 0x04
0x06 0x07

julia> string.(1:3, ". ", ["First", "Second", "Third"])
3-element Vector{String}:
"1. First"
"2. Second"
"3. Third"
```

If you want to prevent a container (like an array) from being iterated over
during broadcasting, you can wrap it in another container (like a
single-element `Tuple`). This will make it behave as a single value during the
broadcast.

```julia
julia> ([1, 2, 3], [4, 5, 6]) .+ ([1, 2, 3],)
([2, 4, 6], [5, 7, 9])

julia> ([1, 2, 3], [4, 5, 6]) .+ tuple([1, 2, 3])
([2, 4, 6], [5, 7, 9])
```

## `@.` syntax

Julia Base also provides a macro, `@.`, which converts every function call or
operator in `expr` into a "dot call" (e.g. convert `f(x)` to `f.(x)`), and converts
every assignment in `expr` to a "dot assignment" (e.g. convert `+=` to `.+=`).

If you want to avoid adding dots for selected function calls in expr, splice
those function calls in with `$`. For example, `@. sqrt(abs($sort(x)))` is
equivalent to `sqrt.(abs.(sort(x)))` (no dot for sort).

TODO

0 comments on commit 9b7afa9

Please sign in to comment.