SliceScatter#
Versioned name: SliceScatter-15
Category: Data movement
Short description: Creates copy of data tensor and applies elements from updates using slicing parametrized by start, stop and step over axes dimensions.
Detailed description:
The operation produces a copy of data tensor and updates it using values specified by updates at specific slices parametrized by start, stop and step values over corresponding axes dimensions.
The output shape and type is the same as data. Number of elements for start, stop, step and axes is required to be equal. Values in axes are required to be unique.
Operator SliceScatter-15 is an equivalent to following NumPy snippet:
def slice_scatter_15(
data: np.ndarray,
updates: np.ndarray,
start: List[int],
stop: List[int],
step: List[int],
axes: Optional[List[int]] = None,
):
out = np.copy(data)
if axes is None:
axes = list(range(len(start)))
slice_list = [slice(None)] * data.ndim
for slice_start, slice_stop, slice_step, slice_axis in zip(start, stop, step, axes):
slice_list[slice_axis] = slice(slice_start, slice_stop, slice_step)
out[tuple(slice_list)] = updates
return out
Attributes: SliceScatter does not have attributes.
Inputs:
1:
datatensor of arbitrary rankr>= 1 and of type T. Required.2:
updates- tensor of type T and same shape asdataexcept axes set byaxeswhere dimensions should be equal to the length of corresponding update slices. Required.3:
start- 1D tensor of type T_IND.Defines the starting coordinate of the update slice in the
datatensor ataxesdimension. A negative index value represents counting elements from the end of that dimension. A value larger than the size of a dimension is silently clamped. Required.4:
stop- 1D tensor of type T_IND.Defines the coordinate of the opposite vertex of the update slice, or where the update slice ends. Stop indexes are exclusive, which means values lying on the ending edge are not updated. A value larger than the size of a dimension is silently clamped. To create slice to the end of a dimension of unknown size
INT_MAXmay be used (orINT_MINif slicing backwards). Required.5:
step- 1D tensor of type T_IND.Integer value that specifies the increment between each index used in slicing. Value cannot be
0, negative value indicates slicing backwards. Required.6:
axes- 1D tensor of type T_AXIS.Optional 1D tensor indicating which dimensions the values in
start,stopandstepapply to. Negative value means counting dimensions from the end. The range is[-r, r - 1], whereris the rank of thedatainput tensor. Values are required to be unique. Default value:[0, 1, 2, ..., start.shape[0] - 1]. Optional.
Number of elements in start, stop, step, and axes inputs are required to be equal.
Outputs:
1: tensor with shape equal to
datatensor of the type T.
Types
T: any numeric type.
T_IND: any supported integer type.
T_AXIS: any supported integer type.
Example
Example 1: Fill slice over axis==0.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>2</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>1</dim>
<dim>5</dim> <!-- values: [[10, 20, 30, 40, 50]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [0] -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [1] -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [1] -->
</port>
<port id="5" precision="I32"> <!-- axes -->
<dim>1</dim> <!-- values: [0] -->
</port>
</input>
<output>
<port id="6" precision="FP32">
<dim>2</dim>
<dim>5</dim> <!-- values: [[10, 20, 30, 40, 50], [5, 6, 7, 8, 9]] -->
</port>
</output>
</layer>
Example 2: Update every second value over axis==1, clamp values of start and stop.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>2</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>2</dim>
<dim>3</dim> <!-- values: [[10, 20, 30], [40, 50, 60]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [-25], silently clamped to 0 -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [25], silently clamped to 5 -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [2] -->
</port>
<port id="5" precision="I32"> <!-- axes -->
<dim>1</dim> <!-- values: [1] -->
</port>
</input>
<output>
<port id="6" precision="FP32">
<dim>2</dim>
<dim>5</dim> <!-- values: [[10, 1, 20, 3, 30], [40, 6, 50, 8, 60]] -->
</port>
</output>
</layer>
Example 3: Update every second value over both axes with different slice starts.
<layer ... type="SliceScatter">
<input>
<port id="0" precision="FP32"> <!-- data -->
<dim>3</dim>
<dim>5</dim> <!-- values: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]] -->
</port>
<port id="1" precision="FP32"> <!-- updates -->
<dim>2</dim>
<dim>2</dim> <!-- values: [[50, 60], [70, 80]] -->
</port>
<port id="2" precision="I32"> <!-- start -->
<dim>1</dim> <!-- values: [0, 1] -->
</port>
<port id="3" precision="I32"> <!-- stop -->
<dim>1</dim> <!-- values: [3, 5] -->
</port>
<port id="4" precision="I32"> <!-- step -->
<dim>1</dim> <!-- values: [2, 2] -->
</port>
</input>
<output>
<port id="5" precision="FP32">
<dim>3</dim>
<dim>5</dim> <!-- values: [[0, 50, 2, 60, 4], [5, 6, 7, 8, 9], [10, 70, 12, 80, 14]] -->
</port>
</output>
</layer>