'Handle the rational function case.'

@classmethod
def _rational_case(cls, poly, func):

    roots = symbols(('r:%d' % poly.degree()))
    (var, expr) = (func.variables[0], func.expr)
    f = sum((expr.subs(var, r) for r in roots))
    (p, q) = together(f).as_numer_denom()
    domain = QQ[roots]
    p = p.expand()
    q = q.expand()
    try:
        p = Poly(p, domain=domain, expand=False)
    except GeneratorsNeeded:
        (p, p_coeff) = (None, (p,))
    else:
        (p_monom, p_coeff) = zip(*p.terms())
    try:
        q = Poly(q, domain=domain, expand=False)
    except GeneratorsNeeded:
        (q, q_coeff) = (None, (q,))
    else:
        (q_monom, q_coeff) = zip(*q.terms())
    (coeffs, mapping) = symmetrize((p_coeff + q_coeff), formal=True)
    (formulas, values) = (viete(poly, roots), [])
    for ((sym, _), (_, val)) in zip(mapping, formulas):
        values.append((sym, val))
    for (i, (coeff, _)) in enumerate(coeffs):
        coeffs[i] = coeff.subs(values)
    n = len(p_coeff)
    p_coeff = coeffs[:n]
    q_coeff = coeffs[n:]
    if (p is not None):
        p = Poly(dict(zip(p_monom, p_coeff)), *p.gens).as_expr()
    else:
        (p,) = p_coeff
    if (q is not None):
        q = Poly(dict(zip(q_monom, q_coeff)), *q.gens).as_expr()
    else:
        (q,) = q_coeff
    return factor((p / q))
