import math


def approx_equal(x, y, tol=1e-12, rel=1e-7):
    """Test whether x is approximately equal to y, using an absolute error
    of tol and/or a relative error of rel, whichever is bigger.

    Pass None as either tol or rel to ignore that test; if both are None,
    the test performed is an exact equality test.

    tol and rel must be either None or a positive, finite number, otherwise
    the behaviour is undefined.
    """
    # Note that the relative error is calculated relative to x only.
    if tol is rel is None:
        # Fall back on exact equality.
        return x == y
    # Infinities and NANs are special.
    if math.isnan(x) or math.isnan(y):
        return False
    delta = abs(x - y)
    if math.isnan(delta):
        # Only if both x and y are the same infinity.
        assert x == y and math.isinf(x)
        return True
    if math.isinf(delta):
        # Either x and y are both infinities with the opposite sign, or
        # one is an infinity and the other is finite. Either way, they're
        # not approximately equal.
        return False
    tests = []
    if tol is not None: tests.append(tol)
    if rel is not None: tests.append(rel*abs(x))
    assert tests
    return delta <= max(tests)