(rv, half=False)
return bottom_up(rv, f)
Converts ratios involving sin and cos as follows::
        sin(x)/cos(x) -> tan(x)
        sin(x)/(cos(x) + 1) -> tan(x/2) if half=True

    Examples
    ========

    >>> from sympy.simplify.fu import TR2i
    >>> from sympy.abc import x, a
    >>> from sympy import sin, cos
    >>> TR2i(sin(x)/cos(x))
    tan(x)

    Powers of the numerator and denominator are also recognized

    >>> TR2i(sin(x)**2/(cos(x) + 1)**2, half=True)
    tan(x/2)**2

    The transformation does not take place unless assumptions allow
    (i.e. the base must be positive or the exponent must be an integer
    for both numerator and denominator)

    >>> TR2i(sin(x)**a/(cos(x) + 1)**a)
    (cos(x) + 1)**(-a)*sin(x)**a
Converts ratios involving sin and cos as follows::
        sin(x)/cos(x) -> tan(x)
        sin(x)/(cos(x) + 1) -> tan(x/2) if half=True
Converts ratios involving sin and cos as follows :: sin ( x ) / cos ( x ) - > tan ( x ) sin ( x ) / ( cos ( x ) + 1 ) - > tan ( x / 2 ) if half = True
def TR2i(rv, half=False):
    """Converts ratios involving sin and cos as follows::
        sin(x)/cos(x) -> tan(x)
        sin(x)/(cos(x) + 1) -> tan(x/2) if half=True

    Examples
    ========

    >>> from sympy.simplify.fu import TR2i
    >>> from sympy.abc import x, a
    >>> from sympy import sin, cos
    >>> TR2i(sin(x)/cos(x))
    tan(x)

    Powers of the numerator and denominator are also recognized

    >>> TR2i(sin(x)**2/(cos(x) + 1)**2, half=True)
    tan(x/2)**2

    The transformation does not take place unless assumptions allow
    (i.e. the base must be positive or the exponent must be an integer
    for both numerator and denominator)

    >>> TR2i(sin(x)**a/(cos(x) + 1)**a)
    (cos(x) + 1)**(-a)*sin(x)**a

    """

    def f(rv):
        if not rv.is_Mul:
            return rv

        n, d = rv.as_numer_denom()
        if n.is_Atom or d.is_Atom:
            return rv

        def ok(k, e):
            # initial filtering of factors
            return (
                (e.is_integer or k.is_positive) and (
                k.func in (sin, cos) or (half and
                k.is_Add and
                len(k.args) >= 2 and
                any(any(ai.func is cos or ai.is_Pow and ai.base is cos
                for ai in Mul.make_args(a)) for a in k.args))))

        n = n.as_powers_dict()
        ndone = [(k, n.pop(k)) for k in list(n.keys()) if not ok(k, n[k])]
        if not n:
            return rv

        d = d.as_powers_dict()
        ddone = [(k, d.pop(k)) for k in list(d.keys()) if not ok(k, d[k])]
        if not d:
            return rv

        # factoring if necessary

        def factorize(d, ddone):
            newk = []
            for k in d:
                if k.is_Add and len(k.args) > 2:
                    knew = factor(k) if half else factor_terms(k)
                    if knew != k:
                        newk.append((k, knew))
            if newk:
                for i, (k, knew) in enumerate(newk):
                    del d[k]
                    newk[i] = knew
                newk = Mul(*newk).as_powers_dict()
                for k in newk:
                    if ok(k, d[k]):
                        d[k] += newk[k]
                    else:
                        ddone.append((k, d[k]))
                del newk
        factorize(n, ndone)
        factorize(d, ddone)

        # joining
        t = []
        for k in n:
            if k.func is sin:
                a = cos(k.args[0], evaluate=False)
                if a in d and d[a] == n[k]:
                    t.append(tan(k.args[0])**n[k])
                    n[k] = d[a] = None
                elif half:
                    a1 = 1 + a
                    if a1 in d and d[a1] == n[k]:
                        t.append((tan(k.args[0]/2))**n[k])
                        n[k] = d[a1] = None
            elif k.func is cos:
                a = sin(k.args[0], evaluate=False)
                if a in d and d[a] == n[k]:
                    t.append(tan(k.args[0])**-n[k])
                    n[k] = d[a] = None
            elif half and k.is_Add and k.args[0] is S.One and \
                    k.args[1].func is cos:
                a = sin(k.args[1].args[0], evaluate=False)
                if a in d and d[a] == n[k] and (d[a].is_integer or \
                        a.is_positive):
                    t.append(tan(a.args[0]/2)**-n[k])
                    n[k] = d[a] = None

        if t:
            rv = Mul(*(t + [b**e for b, e in n.items() if e]))/\
                Mul(*[b**e for b, e in d.items() if e])
            rv *= Mul(*[b**e for b, e in ndone])/Mul(*[b**e for b, e in ddone])

        return rv

    return bottom_up(rv, f)
def TR2i ( rv , half = False ) : def f ( rv ) : if not rv . is_Mul : return rv n , d = rv . as_numer_denom ( ) if n . is_Atom or d . is_Atom : return rv def ok ( k , e ) : # initial filtering of factors return ( ( e . is_integer or k . is_positive ) and ( k . func in ( sin , cos ) or ( half and k . is_Add and len ( k . args ) >= 2 and any ( any ( ai . func is cos or ai . is_Pow and ai . base is cos for ai in Mul . make_args ( a ) ) for a in k . args ) ) ) ) n = n . as_powers_dict ( ) ndone = [ ( k , n . pop ( k ) ) for k in list ( n . keys ( ) ) if not ok ( k , n [ k ] ) ] if not n : return rv d = d . as_powers_dict ( ) ddone = [ ( k , d . pop ( k ) ) for k in list ( d . keys ( ) ) if not ok ( k , d [ k ] ) ] if not d : return rv # factoring if necessary def factorize ( d , ddone ) : newk = [ ] for k in d : if k . is_Add and len ( k . args ) > 2 : knew = factor ( k ) if half else factor_terms ( k ) if knew != k : newk . append ( ( k , knew ) ) if newk : for i , ( k , knew ) in enumerate ( newk ) : del d [ k ] newk [ i ] = knew newk = Mul ( * newk ) . as_powers_dict ( ) for k in newk : if ok ( k , d [ k ] ) : d [ k ] += newk [ k ] else : ddone . append ( ( k , d [ k ] ) ) del newk factorize ( n , ndone ) factorize ( d , ddone ) # joining t = [ ] for k in n : if k . func is sin : a = cos ( k . args [ 0 ] , evaluate = False ) if a in d and d [ a ] == n [ k ] : t . append ( tan ( k . args [ 0 ] ) ** n [ k ] ) n [ k ] = d [ a ] = None elif half : a1 = 1 + a if a1 in d and d [ a1 ] == n [ k ] : t . append ( ( tan ( k . args [ 0 ] / 2 ) ) ** n [ k ] ) n [ k ] = d [ a1 ] = None elif k . func is cos : a = sin ( k . args [ 0 ] , evaluate = False ) if a in d and d [ a ] == n [ k ] : t . append ( tan ( k . args [ 0 ] ) ** - n [ k ] ) n [ k ] = d [ a ] = None elif half and k . is_Add and k . args [ 0 ] is S . One and k . args [ 1 ] . func is cos : a = sin ( k . args [ 1 ] . args [ 0 ] , evaluate = False ) if a in d and d [ a ] == n [ k ] and ( d [ a ] . is_integer or a . is_positive ) : t . append ( tan ( a . args [ 0 ] / 2 ) ** - n [ k ] ) n [ k ] = d [ a ] = None if t : rv = Mul ( * ( t + [ b ** e for b , e in n . items ( ) if e ] ) ) / Mul ( * [ b ** e for b , e in d . items ( ) if e ] ) rv *= Mul ( * [ b ** e for b , e in ndone ] ) / Mul ( * [ b ** e for b , e in ddone ] ) return rv return bottom_up ( rv , f )