Skip to content

Commit f8b0882

Browse files
stevengjararslan
authored andcommitted
Merge pull request #17623 from stevengj/fuse-dotops
make "dot" operations (.+ etc) fusing broadcasts
1 parent 1136846 commit f8b0882

File tree

1 file changed

+40
-16
lines changed

1 file changed

+40
-16
lines changed

docs/src/index.md

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,37 @@ The updating versions of all the binary arithmetic and bitwise operators are:
127127
true
128128
```
129129

130+
## [Vectorized "dot" operators](@id man-dot-operators)
131+
132+
For *every* binary operation like `^`, there is a corresponding
133+
"dot" operation `.^` that is *automatically* defined
134+
to perform `^` element-by-element on arrays. For example,
135+
`[1,2,3] ^ 3` is not defined, since there is no standard
136+
mathematical meaning to "cubing" an array, but `[1,2,3] .^ 3`
137+
is defined as computing the elementwise
138+
(or "vectorized") result `[1^3, 2^3, 3^3]`.
139+
140+
More specifically, `a .^ b` is parsed as the ["dot" call](@ref man-vectorized)
141+
`(^).(a,b)`, which performs a [broadcast](@ref Broadcasting) operation:
142+
it can combine arrays and scalars, arrays of the same size (performing
143+
the operation elementwise), and even arrays of different shapes (e.g.
144+
combining row and column vectors to produce a matrix). Moreover, like
145+
all vectorized "dot calls," these "dot operators" are
146+
*fusing*. For example, if you compute `2 .* A.^2 .+ sin.(A)` for an
147+
array `A`, it performs a *single* loop over `A`, computing `2a^2 + sin(a)`
148+
for each element of `A`. In particular, nested dot calls like `f.(g.(x))`
149+
are fused, and "adjacent" binary operators like `x .+ 3 .* x.^2` are
150+
equivalent to nested dot calls `(+).(x, (*).(3, (^).(x, 2)))`.
151+
152+
Furthermore, "dotted" updating operators like `a .+= b` are parsed
153+
as `a .= a .+ b`, where `.=` is a fused *in-place* assignment operation
154+
(see the [dot syntax documentation](@ref man-vectorized)).
155+
156+
Note the dot syntax is also applicable to user-defined operators.
157+
For example, if you define `⊗(A,B) = kron(A,B)` to give a convenient
158+
infix syntax `A ⊗ B` for Kronecker products ([`kron`](@ref)), then
159+
`[A,B] .⊗ [C,D]` will compute `[A⊗C, B⊗D]` with no additional coding.
160+
130161
## Numeric Comparisons
131162

132163
Standard comparison operations are defined for all the primitive numeric types:
@@ -265,13 +296,6 @@ Chaining comparisons is often quite convenient in numerical code. Chained compar
265296
which allows them to work on arrays. For example, `0 .< A .< 1` gives a boolean array whose entries
266297
are true where the corresponding elements of `A` are between 0 and 1.
267298

268-
The operator [`.<`](@ref) is intended for array objects; the operation `A .< B` is valid only
269-
if `A` and `B` have the same dimensions. The operator returns an array with boolean entries and
270-
with the same dimensions as `A` and `B`. Such operators are called *elementwise*; Julia offers
271-
a suite of elementwise operators: [`.*`](@ref), [`.+`](@ref), etc. Some of the elementwise operators
272-
can take a scalar operand such as the example `0 .< A .< 1` in the preceding paragraph. This notation
273-
means that the scalar operand should be replicated for each entry of the array.
274-
275299
Note the evaluation behavior of chained comparisons:
276300

277301
```julia
@@ -303,15 +327,15 @@ Julia applies the following order of operations, from highest precedence to lowe
303327
| Category | Operators |
304328
|:-------------- |:------------------------------------------------------------------------------------------------- |
305329
| Syntax | `.` followed by `::` |
306-
| Exponentiation | `^` and its elementwise equivalent `.^` |
307-
| Fractions | `//` and `.//` |
308-
| Multiplication | `* / % & \` and `.* ./ .% .\` |
309-
| Bitshifts | `<< >> >>>` and `.<< .>> .>>>` |
310-
| Addition | `+ - \| ⊻` and `.+ .-` |
330+
| Exponentiation | `^` |
331+
| Fractions | `//` |
332+
| Multiplication | `* / % & \` |
333+
| Bitshifts | `<< >> >>>` |
334+
| Addition | `+ - \| ⊻` |
311335
| Syntax | `: ..` followed by `\|>` |
312-
| Comparisons | `> < >= <= == === != !== <:` and `.> .< .>= .<= .== .!=` |
336+
| Comparisons | `> < >= <= == === != !== <:` |
313337
| Control flow | `&&` followed by `\|\|` followed by `?` |
314-
| Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` and `.+= .-= .*= ./= .//= .\= .^= .÷= .%=` |
338+
| Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` |
315339

316340
### Elementary Functions
317341

@@ -321,8 +345,8 @@ including integers, floating-point numbers, rationals, and complexes, wherever s
321345
make sense.
322346

323347
Moreover, these functions (like any Julia function) can be applied in "vectorized" fashion to
324-
arrays and other collections with the syntax `f.(A)`, e.g. `sin.(A)` will compute the elementwise
325-
sine of each element of an array `A`. See [Dot Syntax for Vectorizing Functions](@ref).
348+
arrays and other collections with the [dot syntax](@ref man-vectorized) `f.(A)`,
349+
e.g. `sin.(A)` will compute the elementwise sine of each element of an array `A`.
326350

327351
## Numerical Conversions
328352

0 commit comments

Comments
 (0)