(f, *gens, **args)
Cancel common factors in a rational function ``f``.

    Examples
    ========

    >>> from sympy import cancel, sqrt, Symbol
    >>> from sympy.abc import x
    >>> A = Symbol('A', commutative=False)

    >>> cancel((2*x**2 - 2)/(x**2 - 2*x + 1))
    (2*x + 2)/(x - 1)
    >>> cancel((sqrt(3) + sqrt(15)*A)/(sqrt(2) + sqrt(10)*A))
    sqrt(6)/2
Cancel common factors in a rational function ``f``.
Cancel common factors in a rational function f .
def cancel(f, *gens, **args):
    """
    Cancel common factors in a rational function ``f``.

    Examples
    ========

    >>> from sympy import cancel, sqrt, Symbol
    >>> from sympy.abc import x
    >>> A = Symbol('A', commutative=False)

    >>> cancel((2*x**2 - 2)/(x**2 - 2*x + 1))
    (2*x + 2)/(x - 1)
    >>> cancel((sqrt(3) + sqrt(15)*A)/(sqrt(2) + sqrt(10)*A))
    sqrt(6)/2
    """
    from sympy.core.exprtools import factor_terms
    options.allowed_flags(args, ['polys'])

    f = sympify(f)

    if not isinstance(f, (tuple, Tuple)):
        if f.is_Number or isinstance(f, Relational) or not isinstance(f, Expr):
            return f
        f = factor_terms(f, radical=True)
        p, q = f.as_numer_denom()

    elif len(f) == 2:
        p, q = f
    elif isinstance(f, Tuple):
        return factor_terms(f)
    else:
        raise ValueError('unexpected argument: %s' % f)

    try:
        (F, G), opt = parallel_poly_from_expr((p, q), *gens, **args)
    except PolificationFailed:
        if not isinstance(f, (tuple, Tuple)):
            return f
        else:
            return S.One, p, q
    except PolynomialError as msg:
        if f.is_commutative and not f.has(Piecewise):
            raise PolynomialError(msg)
        # Handling of noncommutative and/or piecewise expressions
        if f.is_Add or f.is_Mul:
            sifted = sift(f.args, lambda x: x.is_commutative and not x.has(Piecewise))
            c, nc = sifted[True], sifted[False]
            nc = [cancel(i) for i in nc]
            return f.func(cancel(f.func._from_args(c)), *nc)
        else:
            reps = []
            pot = preorder_traversal(f)
            next(pot)
            for e in pot:
                # XXX: This should really skip anything that's not Expr.
                if isinstance(e, (tuple, Tuple, BooleanAtom)):
                    continue
                try:
                    reps.append((e, cancel(e)))
                    pot.skip()  # this was handled successfully
                except NotImplementedError:
                    pass
            return f.xreplace(dict(reps))

    c, P, Q = F.cancel(G)

    if not isinstance(f, (tuple, Tuple)):
        return c*(P.as_expr()/Q.as_expr())
    else:
        if not opt.polys:
            return c, P.as_expr(), Q.as_expr()
        else:
            return c, P, Q
def cancel ( f , * gens , * * args ) : from sympy . core . exprtools import factor_terms options . allowed_flags ( args , [ 'polys' ] ) f = sympify ( f ) if not isinstance ( f , ( tuple , Tuple ) ) : if f . is_Number or isinstance ( f , Relational ) or not isinstance ( f , Expr ) : return f f = factor_terms ( f , radical = True ) p , q = f . as_numer_denom ( ) elif len ( f ) == 2 : p , q = f elif isinstance ( f , Tuple ) : return factor_terms ( f ) else : raise ValueError ( 'unexpected argument: %s' % f ) try : ( F , G ) , opt = parallel_poly_from_expr ( ( p , q ) , * gens , * * args ) except PolificationFailed : if not isinstance ( f , ( tuple , Tuple ) ) : return f else : return S . One , p , q except PolynomialError as msg : if f . is_commutative and not f . has ( Piecewise ) : raise PolynomialError ( msg ) # Handling of noncommutative and/or piecewise expressions if f . is_Add or f . is_Mul : sifted = sift ( f . args , lambda x : x . is_commutative and not x . has ( Piecewise ) ) c , nc = sifted [ True ] , sifted [ False ] nc = [ cancel ( i ) for i in nc ] return f . func ( cancel ( f . func . _from_args ( c ) ) , * nc ) else : reps = [ ] pot = preorder_traversal ( f ) next ( pot ) for e in pot : # XXX: This should really skip anything that's not Expr. if isinstance ( e , ( tuple , Tuple , BooleanAtom ) ) : continue try : reps . append ( ( e , cancel ( e ) ) ) pot . skip ( ) # this was handled successfully except NotImplementedError : pass return f . xreplace ( dict ( reps ) ) c , P , Q = F . cancel ( G ) if not isinstance ( f , ( tuple , Tuple ) ) : return c * ( P . as_expr ( ) / Q . as_expr ( ) ) else : if not opt . polys : return c , P . as_expr ( ) , Q . as_expr ( ) else : return c , P , Q