Rounds an uncertainty *unc* following a specific *method* and returns a 2-tuple containing the
    significant digits as a string, and the decimal magnitude that is required to recover the
    uncertainty. *unc* might also be a numpy array. Rounding methods:

    - ``"pdg"``: Rounding rules as defined by the `PDG
      <http://pdg.lbl.gov/2011/reviews/rpp2011-rev-rpp-intro.pdf#page=13>`_.
    - ``"publication"``, ``"pub``: Like ``"pdg"`` with an extra significant digit for results that
      need to be combined later.
    - ``"onedigit"``, ``"one"``: Forces one single significant digit. This is useful when there are
      multiple uncertainties that vary by more than a factor 10 among themselves.

    Example:

    .. code-block:: python

        round_uncertainty(0.123, "pub") # -> ("123", -3)
        round_uncertainty(0.123, "pdg") # -> ("12", -2)
        round_uncertainty(0.123, "one") # -> ("1", -1)

        round_uncertainty(0.456, "pub") # -> ("46", -2)
        round_uncertainty(0.456, "pdg") # -> ("5", -1)
        round_uncertainty(0.456, "one") # -> ("5", -1)

        round_uncertainty(0.987, "pub") # -> ("987", -3)
        round_uncertainty(0.987, "pdg") # -> ("10", -1)
        round_uncertainty(0.987, "one") # -> ("10", -1)

        a = np.array([0.123, 0.456, 0.987])
        round_uncertainty(a, "pub") # -> (["123", "46", "987"], [-3, -2, -3])

def round_uncertainty(unc, method="publication"):
    """
    Rounds an uncertainty *unc* following a specific *method* and returns a 2-tuple containing the
    significant digits as a string, and the decimal magnitude that is required to recover the
    uncertainty. *unc* might also be a numpy array. Rounding methods:

    - ``"pdg"``: Rounding rules as defined by the `PDG
      <http://pdg.lbl.gov/2011/reviews/rpp2011-rev-rpp-intro.pdf#page=13>`_.
    - ``"publication"``, ``"pub``: Like ``"pdg"`` with an extra significant digit for results that
      need to be combined later.
    - ``"onedigit"``, ``"one"``: Forces one single significant digit. This is useful when there are
      multiple uncertainties that vary by more than a factor 10 among themselves.

    Example:

    .. code-block:: python

        round_uncertainty(0.123, "pub") # -> ("123", -3)
        round_uncertainty(0.123, "pdg") # -> ("12", -2)
        round_uncertainty(0.123, "one") # -> ("1", -1)

        round_uncertainty(0.456, "pub") # -> ("46", -2)
        round_uncertainty(0.456, "pdg") # -> ("5", -1)
        round_uncertainty(0.456, "one") # -> ("5", -1)

        round_uncertainty(0.987, "pub") # -> ("987", -3)
        round_uncertainty(0.987, "pdg") # -> ("10", -1)
        round_uncertainty(0.987, "one") # -> ("10", -1)

        a = np.array([0.123, 0.456, 0.987])
        round_uncertainty(a, "pub") # -> (["123", "46", "987"], [-3, -2, -3])
    """
    # validate the method
    meth = method.lower()
    if meth not in ("pub", "publication", "pdg", "one", "onedigit"):
        raise ValueError("unknown rounding method: {}".format(method))

    # split the uncertainty
    sig, mag = split_value(unc)

    # infer the precision based on the method and get updated significand and magnitude
    if not is_numpy(unc):
        prec, sig, mag = _infer_precision(unc, sig, mag, meth)
        replace_args = (".", "")
    else:
        prec = np.ones(unc.shape).astype(np.int)
        for p, u, s, m in np.nditer([prec, unc, sig, mag], op_flags=["readwrite"]):
            p[...], s[...], m[...] = _infer_precision(u, s, m, meth)
        replace_args = (b".", b"")

    # determine the significant digits and the decimal magnitude that would reconstruct the value
    digits = match_precision(sig, 10.**(1 - prec)).replace(*replace_args)
    mag -= prec - 1

    return (digits, mag)