'Expand an expression using hints.
See the docstring of the expand() function in sympy.core.function for
more information.'

@cacheit
def expand(self, deep=True, modulus=None, power_base=True, power_exp=True, mul=True, log=True, multinomial=True, basic=True, **hints):

    from sympy.simplify.radsimp import fraction
    hints.update(power_base=power_base, power_exp=power_exp, mul=mul, log=log, multinomial=multinomial, basic=basic)
    expr = self
    if hints.pop('frac', False):
        (n, d) = [a.expand(deep=deep, modulus=modulus, **hints) for a in fraction(self)]
        return (n / d)
    elif hints.pop('denom', False):
        (n, d) = fraction(self)
        return (n / d.expand(deep=deep, modulus=modulus, **hints))
    elif hints.pop('numer', False):
        (n, d) = fraction(self)
        return (n.expand(deep=deep, modulus=modulus, **hints) / d)
    def _expand_hint_key(hint):
        'Make    multinomial    come    before    mul'
        if (hint == 'mul'):
            return 'mulz'
        return hint
    for hint in sorted(hints.keys(), key=_expand_hint_key):
        use_hint = hints[hint]
        if use_hint:
            hint = ('_eval_expand_' + hint)
            (expr, hit) = Expr._expand_hint(expr, hint, deep=deep, **hints)
    while True:
        was = expr
        if hints.get('multinomial', False):
            (expr, _) = Expr._expand_hint(expr, '_eval_expand_multinomial', deep=deep, **hints)
        if hints.get('mul', False):
            (expr, _) = Expr._expand_hint(expr, '_eval_expand_mul', deep=deep, **hints)
        if hints.get('log', False):
            (expr, _) = Expr._expand_hint(expr, '_eval_expand_log', deep=deep, **hints)
        if (expr == was):
            break
    if (modulus is not None):
        modulus = sympify(modulus)
        if ((not modulus.is_Integer) or (modulus <= 0)):
            raise ValueError(('modulus    must    be    a    positive    integer,    got    %s' % modulus))
        terms = []
        for term in Add.make_args(expr):
            (coeff, tail) = term.as_coeff_Mul(rational=True)
            coeff %= modulus
            if coeff:
                terms.append((coeff * tail))
        expr = Add(*terms)
    return expr
