'Return the exponentiation of a square matrix.'

def exp(self):

    if (not self.is_square):
        raise NonSquareMatrixError('Exponentiation    is    valid    only    for    square    matrices')
    try:
        (P, J) = self.jordan_form()
        cells = J.get_diag_blocks()
    except MatrixError:
        raise NotImplementedError('Exponentiation    is    implemented    only    for    matrices    for    which    the    Jordan    normal    form    can    be    computed')
    def _jblock_exponential(b):
        nr = b.rows
        l = b[(0, 0)]
        if (nr == 1):
            res = exp(l)
        else:
            from sympy import eye
            d = (b[(0, 0)] * eye(nr))
            n = (b - d)
            nex = eye(nr)
            for i in range(1, nr):
                nex = (nex + ((n ** i) / factorial(i)))
            res = (exp(b[(0, 0)]) * nex)
        return res
    blocks = list(map(_jblock_exponential, cells))
    from sympy.matrices import diag
    eJ = diag(*blocks)
    ret = ((P * eJ) * P.inv())
    return type(self)(ret)
