6. Ranges
A range consists of two cells, the start and end cells of the range, separated by a colon.
For example, A0:B9 (or A0:C1R9, or R0C0:R9C1, or C0R0:R9C1, etc.)
specifies a range including rows 0 to 9 of columns A and B.
The range start and end values do not have to be
in increasing order; B9:A0, B0:A9, and A9:B0 all refer to the same group of
cells as A0:B9, but correspond to different directions for traversing the
range. For example the command copy a0:a9 b9:b0 would copy column b to a
in reverse order.
By default, ranges are traversed byrows to improve cache performance, since elements in a row are adjacent in memory. That is, in pseudo-code:
  for row = start_row to end_row
    for col = start_col to end_col
      use cell[row,col]
The bycols option can be used globally or with
various commands (copy, eval, fill, etc.)
to cause evaluation by columns.
That is, in pseudo-code:
  for col = start_col to end_col
    for row = start_row to end_row
      use cell[row,col]
Note that the starting row may be less than, equal to, or greater than the
ending row.  Same for columns.  So a range may consist of a single cell,
row, or column (a0:a0, a0:d0, a0:a4), cells in "increasing" order (a0:b4), or
cells in "partial decreasing" order (a4:b0, b0:a4), or cells in "decreasing"
order (b4:a0).
A range basically represents a list of cells, and is explicitly converted to a list when used as a numeric function argument.
A range consisting of a single cell may be specified using just that one cell, e.g. A0 as a range is the same as A0:A0.