Try to decompose a cirq.Operation or cirq.Gate, and return its unitary
    if it exists.

    Returns:
        If `val` can be decomposed into unitaries, calculate the resulting
        unitary and return it. If it doesn't exist, None is returned.

def _decompose_and_get_unitary(val: Union['cirq.Operation', 'cirq.Gate']
                               ) -> np.ndarray:
    """Try to decompose a cirq.Operation or cirq.Gate, and return its unitary
    if it exists.

    Returns:
        If `val` can be decomposed into unitaries, calculate the resulting
        unitary and return it. If it doesn't exist, None is returned.
    """
    from cirq.protocols.apply_unitary import apply_unitary, ApplyUnitaryArgs
    from cirq.protocols.decompose import (decompose_once,
                                          decompose_once_with_qubits)
    from cirq import Gate, LineQubit, Operation

    if isinstance(val, Operation):
        qubits = val.qubits
        decomposed_val = decompose_once(val, default=None)
    elif isinstance(val, Gate):
        # Since gates don't know about qubits, we need to create some
        qubits = tuple(LineQubit.range(val.num_qubits()))
        decomposed_val = decompose_once_with_qubits(val,
                                                    qubits,
                                                    default=None)

    if decomposed_val is not None:
        # Calculate the resulting unitary (if it exists)
        n = len(qubits)
        state = np.eye(1 << n, dtype=np.complex128)
        state.shape = (2,) * (2 * n)
        buffer = np.zeros(state.shape, dtype=np.complex128)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        result = state
        for op in decomposed_val:
            indices = [qubit_map[q] for q in op.qubits]
            result = apply_unitary(
                unitary_value=op,
                args=ApplyUnitaryArgs(state, buffer, indices),
                default=None)
            if result is None:
                return None
            if result is buffer:
                buffer = state
            state = result
        if result is not None:
            return result.reshape((1 << n, 1 << n))