def __init__(
        self,
        target_tensor: np.ndarray,
        available_buffer: np.ndarray,
        axes: Iterable[int],
        subspaces: Sequence[tuple[int, ...]] | None = None,
    ):
        """Inits ApplyUnitaryArgs.

        Args:
            target_tensor: The input tensor that needs to be left-multiplied by
                the unitary effect of the receiving object. The tensor will
                have the shape (2, 2, 2, ..., 2). It usually corresponds to
                a multi-qubit superposition, but it could also be a multi-qubit
                unitary transformation or some other concept.
            available_buffer: Pre-allocated workspace with the same shape and
                dtype as the target tensor.
            axes: Which axes the unitary effect is being applied to (e.g. the
                qubits that the gate is operating on).
            subspaces: Which subspace (in the computational basis) the unitary
                effect is being applied to, on each axis. By default it applies
                to subspace 0..d-1 on each axis, where d is the dimension of
                the unitary effect on that axis. Subspaces on each axis must be
                representable as a slice, so the dimensions specified here need
                to have a consistent step size.
        Raises:
            ValueError: If the subspace count does not equal the axis count, if
                any subspace has zero dimensions, or if any subspace has
                dimensions specified without a consistent step size.
        """
        self.target_tensor = target_tensor
        self.available_buffer = available_buffer
        self.axes = tuple(axes)
        if subspaces is not None:
            if len(self.axes) != len(subspaces):
                raise ValueError('Subspace count does not match axis count.')
            for subspace, axis in zip(subspaces, self.axes):
                if any(s >= target_tensor.shape[axis] for s in subspace):
                    raise ValueError('Subspace specified does not exist in axis.')
        self.slices = None if subspaces is None else tuple(map(_to_slice, subspaces))
Inits ApplyUnitaryArgs.

        Args:
            target_tensor: The input tensor that needs to be left-multiplied by
                the unitary effect of the receiving object. The tensor will
                have the shape (2, 2, 2, ..., 2). It usually corresponds to
                a multi-qubit superposition, but it could also be a multi-qubit
                unitary transformation or some other concept.
            available_buffer: Pre-allocated workspace with the same shape and
                dtype as the target tensor.
            axes: Which axes the unitary effect is being applied to (e.g. the
                qubits that the gate is operating on).
            subspaces: Which subspace (in the computational basis) the unitary
                effect is being applied to, on each axis. By default it applies
                to subspace 0..d-1 on each axis, where d is the dimension of
                the unitary effect on that axis. Subspaces on each axis must be
                representable as a slice, so the dimensions specified here need
                to have a consistent step size.
        Raises:
            ValueError: If the subspace count does not equal the axis count, if
                any subspace has zero dimensions, or if any subspace has
                dimensions specified without a consistent step size.
        
cirq-core/cirq/protocols/apply_unitary_protocol.py