octave: Broadcasting

 
 19.2 Broadcasting
 =================
 
 Broadcasting refers to how Octave binary operators and functions behave
 when their matrix or array operands or arguments differ in size.  Since
 version 3.6.0, Octave now automatically broadcasts vectors, matrices,
 and arrays when using elementwise binary operators and functions.
 Broadly speaking, smaller arrays are “broadcast” across the larger one,
 until they have a compatible shape.  The rule is that corresponding
 array dimensions must either
 
   1. be equal, or
 
   2. one of them must be 1.
 
 In case all dimensions are equal, no broadcasting occurs and ordinary
 element-by-element arithmetic takes place.  For arrays of higher
 dimensions, if the number of dimensions isn’t the same, then missing
 trailing dimensions are treated as 1.  When one of the dimensions is 1,
 the array with that singleton dimension gets copied along that dimension
 until it matches the dimension of the other array.  For example,
 consider
 
      x = [1 2 3;
           4 5 6;
           7 8 9];
 
      y = [10 20 30];
 
      x + y
 
 Without broadcasting, ‘x + y’ would be an error because the dimensions
 do not agree.  However, with broadcasting it is as if the following
 operation were performed:
 
      x = [1 2 3
           4 5 6
           7 8 9];
 
      y = [10 20 30
           10 20 30
           10 20 30];
 
      x + y
      ⇒    11   22   33
            14   25   36
            17   28   39
 
 That is, the smaller array of size ‘[1 3]’ gets copied along the
 singleton dimension (the number of rows) until it is ‘[3 3]’.  No actual
 copying takes place, however.  The internal implementation reuses
 elements along the necessary dimension in order to achieve the desired
 effect without copying in memory.
 
    Both arrays can be broadcast across each other, for example, all
 pairwise differences of the elements of a vector with itself:
 
      y - y'
      ⇒    0   10   20
          -10    0   10
          -20  -10    0
 
 Here the vectors of size ‘[1 3]’ and ‘[3 1]’ both get broadcast into
 matrices of size ‘[3 3]’ before ordinary matrix subtraction takes place.
 
    A special case of broadcasting that may be familiar is when all
 dimensions of the array being broadcast are 1, i.e., the array is a
 scalar.  Thus for example, operations like ‘x - 42’ and ‘max (x, 2)’ are
 basic examples of broadcasting.
 
    For a higher-dimensional example, suppose ‘img’ is an RGB image of
 size ‘[m n 3]’ and we wish to multiply each color by a different scalar.
 The following code accomplishes this with broadcasting,
 
      img .*= permute ([0.8, 0.9, 1.2], [1, 3, 2]);
 
 Note the usage of permute to match the dimensions of the ‘[0.8, 0.9,
 1.2]’ vector with ‘img’.
 
    For functions that are not written with broadcasting semantics,
 ‘bsxfun’ can be useful for coercing them to broadcast.
 
  -- : bsxfun (F, A, B)
      The binary singleton expansion function performs broadcasting, that
      is, it applies a binary function F element-by-element to two array
      arguments A and B, and expands as necessary singleton dimensions in
      either input argument.
 
      F is a function handle, inline function, or string containing the
      name of the function to evaluate.  The function F must be capable
      of accepting two column-vector arguments of equal length, or one
      column vector argument and a scalar.
 
      The dimensions of A and B must be equal or singleton.  The
      singleton dimensions of the arrays will be expanded to the same
      dimensionality as the other array.
 
      See also: Seearrayfun XREFarrayfun, Seecellfun XREFcellfun.
 
    Broadcasting is only applied if either of the two broadcasting
 conditions hold.  As usual, however, broadcasting does not apply when
 two dimensions differ and neither is 1:
 
      x = [1 2 3
           4 5 6];
      y = [10 20
           30 40];
      x + y
 
 This will produce an error about nonconformant arguments.
 
    Besides common arithmetic operations, several functions of two
 arguments also broadcast.  The full list of functions and operators that
 broadcast is
 
            plus      +  .+
            minus     -  .-
            times     .*
            rdivide   ./
            ldivide   .\
            power     .^  .**
            lt        <
            le        <=
            eq        ==
            gt        >
            ge        >=
            ne        !=  ~=
            and       &
            or        |
            atan2
            hypot
            max
            min
            mod
            rem
            xor
 
            +=  -=  .+=  .-=  .*=  ./=  .\=  .^=  .**=  &=  |=
 
    Beware of resorting to broadcasting if a simpler operation will
 suffice.  For matrices A and B, consider the following:
 
      C = sum (permute (A, [1, 3, 2]) .* permute (B, [3, 2, 1]), 3);
 
 This operation broadcasts the two matrices with permuted dimensions
 across each other during elementwise multiplication in order to obtain a
 larger 3-D array, and this array is then summed along the third
 dimension.  A moment of thought will prove that this operation is simply
 the much faster ordinary matrix multiplication, ‘C = A*B;’.
 
    A note on terminology: “broadcasting” is the term popularized by the
 Numpy numerical environment in the Python programming language.  In
 other programming languages and environments, broadcasting may also be
 known as _binary singleton expansion_ (BSX, in MATLAB, and the origin of
 the name of the ‘bsxfun’ function), _recycling_ (R programming
 language), _single-instruction multiple data_ (SIMD), or _replication_.
 
 19.2.1 Broadcasting and Legacy Code
 -----------------------------------
 
 The new broadcasting semantics almost never affect code that worked in
 previous versions of Octave.  Consequently, all code inherited from
 MATLAB that worked in previous versions of Octave should still work
 without change in Octave.  The only exception is code such as
 
      try
        c = a.*b;
      catch
        c = a.*a;
      end_try_catch
 
 that may have relied on matrices of different size producing an error.
 Because such operation is now valid Octave syntax, this will no longer
 produce an error.  Instead, the following code should be used:
 
      if (isequal (size (a), size (b)))
        c = a .* b;
      else
        c = a .* a;
      endif