//  [python]
def _apply_synthetic_array(self, rx_rot_mat, tx_rot_mat, paths, paths_tmp):
        # pylint: disable=line-too-long
        r"""
        Applies the phase shifts to simulate the effect of a synthetic array
        on a planar wave

        Input
        ------
        rx_rot_mat : [num_rx, 3, 3], tf.float
            Matrices for rotating according to the receivers orientations

        tx_rot_mat : [num_tx, 3, 3], tf.float
            Matrices for rotating according to the receivers orientations

        paths_tmp : :class:`~sionna.rt.PathsTmpData`
            Addtional quantities required for paths computation

        Output
        -------
        paths : :class:`~sionna.rt.PathsTmpData`
            Updated paths
        """

        # [num_rx, num_rx_patterns, 1, num_tx, num_tx_patterns, 1,
        #   max_num_paths]
        a = paths.a
        # [num_rx, num_tx, samples_per_tx, 3]
        k_tx = paths_tmp.k_tx
        # [num_tx, num_tx, samples_per_tx, 3]
        k_rx = paths_tmp.k_rx

        two_pi = tf.cast(2.*PI, self._rdtype)

        # Relative positions of the antennas of the transmitters and receivers
        # rx_rel_ant_pos: [num_rx, rx_array_size, 3], tf.float
        #     Relative positions of the receivers antennas
        # tx_rel_ant_pos: [num_tx, rx_array_size, 3], tf.float
        #     Relative positions of the transmitters antennas
        rx_rel_ant_pos, tx_rel_ant_pos =\
            self._get_antennas_relative_positions(rx_rot_mat, tx_rot_mat)

        # Expand dims for broadcasting with antennas
        # The receive vector is flipped as we need vectors that point away
        # from the arrays.
        # [num_rx, 1, 1, num_tx, 1, 1, max_num_paths, 3]
        k_rx = insert_dims(insert_dims(k_rx, 2, 1), 2, 4)
        k_tx = insert_dims(insert_dims(k_tx, 2, 1), 2, 4)
        # Compute the synthetic phase shifts due to the antenna array
        # Transmitter side
        # Expand for broadcasting with receiver, receive antennas,
        # paths
        # [1, 1, 1, num_tx, tx_array_size, 3]
        tx_rel_ant_pos = insert_dims(tx_rel_ant_pos, 3, axis=0)
        # [1, 1, 1, num_tx, 1, tx_array_size, 1, 3]
        tx_rel_ant_pos = tf.expand_dims(tf.expand_dims(tx_rel_ant_pos, axis=4),
                                        axis=6)
        # [num_rx, 1, 1, num_tx, 1, tx_array_size, max_num_paths]
        tx_phase_shifts = dot(tx_rel_ant_pos, k_tx)
        # Receiver side
        # Expand for broadcasting with transmitter, transmit antennas,
        # paths
        # [num_rx, 1, rx_array_size, 1, 1, 1, 1, 3]
        rx_rel_ant_pos = insert_dims(tf.expand_dims(rx_rel_ant_pos, axis=1),
                                     4, axis=3)
        # [num_rx, 1, rx_array_size, num_tx, 1, 1, 1, max_num_paths]
        rx_phase_shifts = dot(rx_rel_ant_pos, k_rx)
        # Total phase shift
        # [num_rx, 1, rx_array_size, num_tx, 1, tx_array_size, max_num_paths]
        phase_shifts = rx_phase_shifts + tx_phase_shifts
        phase_shifts = two_pi*phase_shifts/self._scene.wavelength
        # Apply the phase shifts
        # Broadcast is not supported by TF for such high rank tensors.
        # We therefore do it manually
        # [num_rx, num_rx_patterns, rx_array_size, num_tx, num_tx_patterns,
        #   tx_array_size, max_num_paths]
        a = tf.tile(a, [1, 1, phase_shifts.shape[2], 1, 1,
                        phase_shifts.shape[5], 1])
        # [num_rx, num_rx_patterns, rx_array_size, num_tx, num_tx_patterns,
        #   tx_array_size, max_num_paths]
        a = a*tf.exp(tf.complex(tf.zeros_like(phase_shifts), phase_shifts))
        a = flatten_dims(flatten_dims(a, 2, 1), 2, 3)

        return a