Produces a result array identical to x except that slices at
positions specified by scatter_indices are updated with values from
the update array. When multiple indices point to the same location,
the update_fn function determines how to combine the values
(by default the new value replaces the old one).
This is the inverse of prim_gather(): gather reads slices from an array
at given indices, while scatter writes slices into an array at given
indices.
Usage
prim_scatter(
x,
scatter_indices,
update,
update_window_axes,
inserted_window_axes,
x_batching_axes,
scatter_indices_batching_axes,
scatter_axes_to_x_axes,
index_vector_axis,
indices_are_sorted = FALSE,
unique_indices = FALSE,
update_fn = "replace"
)Arguments
- x
(
arrayish)
The base array to scatter into. Can be any data type.xandupdatemust have the same data type. An R value among them assumes the data type of the others when it is in its data type category, and its default data type when none of them has one.- scatter_indices
(
arrayish)
Array of indices, of an integer data type, which it keeps – the indices take no part inx's. Contains index vectors that map to positions inxviascatter_axes_to_x_axes. The axis specified byindex_vector_axisholds the index vectors.- update
(
arrayish)
Update values array. Sharesx's data type – seex.- update_window_axes
(
integer())
Axes ofupdatethat are window axes, i.e. they correspond to the slice being written intox.- inserted_window_axes
(
integer())
Axes ofxwhose slices have size 1 and are inserted (not present) in theupdatewindow. Together withupdate_window_axesandx_batching_axes, these must account for all axes ofx.- x_batching_axes
(
integer())
Axes ofxthat are batch axes. Useinteger(0)when there are no batch axes.- scatter_indices_batching_axes
(
integer())
Axes ofscatter_indicesthat correspond to batch axes. Must have the same length asx_batching_axes.- scatter_axes_to_x_axes
(
integer())
Maps each component of an index vector inscatter_indicesto an axis ofx. For example,scatter_axes_to_x_axes = 1Lmeans each index vector indexes into the first axis ofx. This isprim_gather()'sstart_index_map.- index_vector_axis
(
integer(1))
Axis ofscatter_indicesthat contains the index vectors. If set tonaxes(scatter_indices) + 1, each scalar element ofscatter_indicesis treated as a length-1 index vector.- indices_are_sorted
(
logical(1))
Whether indices are guaranteed to be sorted. Setting toTRUEmay improve performance but produces undefined behavior if the indices are not actually sorted. DefaultFALSE.- unique_indices
(
logical(1))
Whether indices are guaranteed to be unique (no duplicates). Setting toTRUEmay improve performance but produces undefined behavior if the indices are not actually unique. DefaultFALSE.- update_fn
(
character(1)|function)
How an update combines with the value inxit lands on. One of"replace"(the default): the update replaces the value,"add","sub","mul": the value plus, minus or times the update,"max","min": the larger or the smaller of the two,
or a binary function
f(old, new)of two scalars atx's data type, which returns one. Only a namedupdate_fncan be differentiated, see section Gradients.
Value
(arrayish)
Has the same data type and shape as x.
Out of Bounds Behavior
If a computed result index falls outside the bounds of x, the
update for that index is silently ignored.
Update Order
When multiple indices in scatter_indices map to the same element
of x, update_fn combines each of their updates with it in turn, so
"add" adds them all up. The order is implementation-defined and may vary
between plugins ("cpu", "cuda"), which matters for "replace", where one
of them is the one that ends up written.
Gradients
gradient() differentiates a scatter whose update_fn is one of the names,
but not a function, even one that computes the same.
With
"replace", an update gets the gradient only where it is the one that was written.With
"mul", the gradient with respect toupdateneedsunique_indices = TRUE.With
"max"and"min",xand the updates that tie for the result share its gradient equally.
An update that falls outside of x, and is therefore ignored, gets a
gradient of zero.
StableHLO
Lowers to hlo_scatter(), specified under
scatter.
The axis and index arguments are intricate; anvl states them in its own
terms and converts on the way down.
See also
prim_gather(), nv_subset(), nv_subset_assign(), [, [<-
Examples
# scatter values 10 and 30 into positions 1 and 3 of a zero vector
x <- nv_array(c(0, 0, 0, 0, 0))
indices <- nv_matrix(c(1L, 3L), ncol = 1)
updates <- nv_array(c(10, 30))
prim_scatter(
x, indices, updates,
update_window_axes = integer(0),
inserted_window_axes = 1L,
x_batching_axes = integer(0),
scatter_indices_batching_axes = integer(0),
scatter_axes_to_x_axes = 1L,
index_vector_axis = 2L
)
#> AnvlArray
#> 10
#> 0
#> 30
#> 0
#> 0
#> [ CPUf32{5} ]