'Tries to do some simplifications on self**expt
Returns None if no further simplifications can be done
When exponent is a fraction (so we have for example a square root),
we try to find a simpler representation by factoring the argument
up to factors of 2**15, e.g.
- sqrt(4) becomes 2
- sqrt(-4) becomes 2*I
- (2**(3+7)*3**(6+7))**Rational(1,7) becomes 6*18**(3/7)
Further simplification would require a special call to factorint on
the argument which is not done here for sake of speed.'

def _eval_power(self, expt):

    from sympy import perfect_power
    if (expt is S.Infinity):
        if (self.p > S.One):
            return S.Infinity
        return (S.Infinity + (S.ImaginaryUnit * S.Infinity))
    if (expt is S.NegativeInfinity):
        return (Rational(1, self) ** S.Infinity)
    if (not isinstance(expt, Number)):
        if (self.is_negative and expt.is_even):
            return ((- self) ** expt)
    if isinstance(expt, Float):
        return super(Integer, self)._eval_power(expt)
    if (not isinstance(expt, Rational)):
        return
    if ((expt is S.Half) and self.is_negative):
        return (S.ImaginaryUnit * Pow((- self), expt))
    if expt.is_negative:
        ne = (- expt)
        if self.is_negative:
            if (expt.q != 1):
                return ((- (S.NegativeOne ** ((expt.p % expt.q) / S(expt.q)))) * (Rational(1, (- self)) ** ne))
            else:
                return ((S.NegativeOne ** ne) * (Rational(1, (- self)) ** ne))
        else:
            return (Rational(1, self.p) ** ne)
    (x, xexact) = integer_nthroot(abs(self.p), expt.q)
    if xexact:
        result = Integer((x ** abs(expt.p)))
        if self.is_negative:
            result *= (S.NegativeOne ** expt)
        return result
    b_pos = int(abs(self.p))
    p = perfect_power(b_pos)
    if (p is not False):
        dict = {p[0]: p[1]}
    else:
        dict = Integer(self).factors(limit=(2 ** 15))
    if self.is_negative:
        dict[(-1)] = 1
    out_int = 1
    out_rad = 1
    sqr_int = 1
    sqr_gcd = 0
    sqr_dict = {}
    for (prime, exponent) in dict.items():
        exponent *= expt.p
        (div_e, div_m) = divmod(exponent, expt.q)
        if (div_e > 0):
            out_int *= (prime ** div_e)
        if (div_m > 0):
            g = igcd(div_m, expt.q)
            if (g != 1):
                out_rad *= Pow(prime, Rational((div_m // g), (expt.q // g)))
            else:
                sqr_dict[prime] = div_m
    for (p, ex) in sqr_dict.items():
        if (sqr_gcd == 0):
            sqr_gcd = ex
        else:
            sqr_gcd = igcd(sqr_gcd, ex)
            if (sqr_gcd == 1):
                break
    for (k, v) in sqr_dict.items():
        sqr_int *= (k ** (v // sqr_gcd))
    if ((sqr_int == self) and (out_int == 1) and (out_rad == 1)):
        result = None
    else:
        result = ((out_int * out_rad) * Pow(sqr_int, Rational(sqr_gcd, expt.q)))
    return result
