nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/linalg/ops/transforms/Transforms.java
public static INDArray mpow(INDArray in, int n, boolean dup) {
        assert in.rows() == in.columns();
        if (n == 0) {
            if (dup)
                return Nd4j.eye(in.rows());
            else
                return in.assign(Nd4j.eye(in.rows()));
        }
        INDArray temp;
        if (n < 0) {
            temp = InvertMatrix.invert(in, !dup);
            n = -n;
        } else
            temp = in.dup();
        INDArray result = temp.dup();
        if (n < 4) {
            for (int i = 1; i < n; i++) {
                result.mmuli(temp);
            }
            if (dup)
                return result;
            else
                return in.assign(result);
        } else {
            // lets try to optimize by squaring itself a bunch of times
            int squares = (int) (Math.log(n) / Math.log(2.0));
            for (int i = 0; i < squares; i++)
                result = result.mmul(result);
            int diff = (int) Math.round(n - Math.pow(2.0, squares));
            for (int i = 0; i < diff; i++)
                result.mmuli(temp);
            if (dup)
                return result;
            else
                return in.assign(result);
        }
    }
public static INDArray mpow(INDArray in, int n, boolean dup) {
        assert in.rows() == in.columns();
        if (n == 0) {
            if (dup)
                return Nd4j.eye(in.rows());
            else
                return in.assign(Nd4j.eye(in.rows()));
        }
        INDArray temp;
        if (n < 0) {
            temp = InvertMatrix.invert(in, !dup);
            n = -n;
        } else
            temp = in.dup();
        INDArray result = temp.dup();
        if (n < 4) {
            for (int i = 1; i < n; i++) {
                result.mmuli(temp);
            }
            if (dup)
                return result;
            else
                return in.assign(result);
        } else {
            // lets try to optimize by squaring itself a bunch of times
            int squares = (int) (Math.log(n) / Math.log(2.0));
            for (int i = 0; i < squares; i++)
                result = result.mmul(result);
            int diff = (int) Math.round(n - Math.pow(2.0, squares));
            for (int i = 0; i < diff; i++)
                result.mmuli(temp);
            if (dup)
                return result;
            else
                return in.assign(result);
        }
    }
Raises a square matrix to a power <i>n</i>, which can be positive, negative, or zero.
The behavior is similar to the numpy matrix_power() function.  The algorithm uses
repeated squarings to minimize the number of mmul() operations needed
<p>If <i>n</i> is zero, the identity matrix is returned.</p>
<p>If <i>n</i> is negative, the matrix is inverted and raised to the abs(n) power.</p>
@param in A square matrix to raise to an integer power, which will be changed if dup is false.
@param n The integer power to raise the matrix to.
@param dup If dup is true, the original input is unchanged.
@return The result of raising <i>in</i> to the <i>n</i>th power.