private ArrayList<Polynomial> factor3(int maxdegree) throws Exception { 
        // http://planetmath.org/encyclopedia/DistinctDegreeFactorization.html
        Polynomial p = this;
        ArrayList<Polynomial> factors = new ArrayList<Polynomial>();
    
        // x^(q^k) - x mod p contains all the degree-k irreducible polys, q = |F|
        // We start it off with k == 0 which gives xqkx = 0.
        Polynomial xqkx = zero();
    
        // try all degrees which might be a factor of p.
        // (if p is reducible, it must have a factor of degree <= p.degree()/2)
        // use may have a maxdegree specified that is smaller
        int md = p.degree()/2;
        md = maxdegree < md ? maxdegree : md; 
        for (int k = 1; k <= md; k++) {
            // compute xqkx from previous value
            // - add x
            // - raise to the qth power x^(q^k) = (x^(q^(k-1)))^q
            // - subtract x
            xqkx = xqkx.add(x()).modPow(PF.order(), p).sub(x());
  
            // compute gcd with p
            Polynomial d = p.gcd(xqkx);
            if (d.degree() > 0) {
                if (d.degree() == k) {          // exactly one factor of degree k
                    factors.add(d);
                } else {                        // several factors of degree k
                    factors.addAll(d.factor4(k));
                }
                p = p.div(d)[0];
                if (p.degree() == 0) return factors;
            }
        }   
        // remaining polynomial must be irreducible
        factors.add(p);
        return factors;
    }