private ArrayList<Polynomial> factor4(int d) throws Exception {
        // Cantor-Zassenhaus algorithm
        Random r = new Random();
        Polynomial p = this;
        long e = PF.sub(PF.pow(PF.order(), d), 1L) / 2;
            
        while (true) {
            // pick a random t of degree < 2d
            long[] elts = new long[2*d];
            for (int i = 0; i < elts.length; i++) {
                elts[i] = PF.random(r);
            }
            Polynomial t = new Polynomial(elts);
          
            // compute t^((q^d - 1) / 2) - 1 mod p
            t = t.modPow(e, p).sub(one());
            
            // hopefully t and p have a factor in common
            Polynomial f = p.gcd(t);
            if (f.degree() > 0 && f.degree() < p.degree()) {  // found a factor of p
                Polynomial f1 = f;
                Polynomial f2 = p.div(f)[0];
        
                ArrayList<Polynomial> factors = new ArrayList<Polynomial>();
                if (f1.degree() == d) {
                    factors.add(f1);
                } else {
                    factors.addAll(f1.factor4(d));
                }
                if (f2.degree() == d) {
                    factors.add(f2);
                } else {
                    factors.addAll(f2.factor4(d));
                }
                return factors;
            }
        }
    }