Implements a single-qubit operation with a PhasedX and Z gate.

    If one of the gates isn't needed, it will be omitted.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        atol: A limit on the amount of error introduced by the
            construction.

    Returns:
        A list of gates that, when applied in order, perform the desired
            operation.

def single_qubit_matrix_to_phased_x_z(
        mat: np.ndarray,
        atol: float = 0
) -> List[ops.SingleQubitGate]:
    """Implements a single-qubit operation with a PhasedX and Z gate.

    If one of the gates isn't needed, it will be omitted.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        atol: A limit on the amount of error introduced by the
            construction.

    Returns:
        A list of gates that, when applied in order, perform the desired
            operation.
    """

    xy_turn, xy_phase_turn, total_z_turn = (
        _deconstruct_single_qubit_matrix_into_gate_turns(mat))

    # Build the intended operation out of non-negligible XY and Z rotations.
    result = [
        ops.PhasedXPowGate(exponent=2 * xy_turn,
                           phase_exponent=2 * xy_phase_turn),
        ops.Z**(2 * total_z_turn)
    ]
    result = [
        g for g in result
        if protocols.trace_distance_bound(g) > atol
    ]

    # Special case: XY half-turns can absorb Z rotations.
    if len(result) == 2 and abs(xy_turn) >= 0.5 - atol:
        return [
            ops.PhasedXPowGate(phase_exponent=2 * xy_phase_turn + total_z_turn)
        ]

    return result