protected Vector<BigIntegerPoly> i2roots()
        {
                /* The vector of the factors to be returned
                */
                Vector<BigIntegerPoly> res =new Vector<BigIntegerPoly>() ;

                if ( degree() < 2)
                        return res ;

                BigInteger bsco = a.firstElement().abs() ;
                Vector<BigInteger> b = BigIntegerMath.divisors(bsco) ;
                BigInteger csco = a.lastElement().abs() ;
                Vector<BigInteger> c = BigIntegerMath.divisors(csco) ;

                /* Generate the floating point values of roots. To have some reasonable
                * accuracy in the results, add zeros to the integer coefficients, scaled
                * by the expected division with values of b (which are all <= a.firstele).
                * Number of decimal digits in bsco by using a log2->log10 rough estimate
                * and adding 6 safety digits
                */
                RatPoly thisDec = toRatPoly() ;
                Vector<BigComplex> roo = thisDec.roots(6+(int)(0.3*bsco.bitCount()) ) ;

                final BigDecimal half = new BigDecimal("0.5") ;

                /* for each of the roots z try to see whether c*z^2+a*z+b=0 with integer a, b and c
                * where b is restricted to a signed divisor of the constant coefficient.
                * Solve z*(c*z+a)=-b or c*z+a = -b/z or -b/z-c*z = some integer a.
                */
                for( BigComplex z : roo)
                {
                        for(BigInteger bco : b)
                        for(BigInteger cco : c)
                        {
                                /* the major reason to avoid the case b=0 is that this would
                                * require precaution of double counting below. Note that this
                                * case is already covered by using iroots().
                                */
                                if ( bco.signum() != 0 )
                                {
                                        for(int sig = -1 ; sig <=1 ; sig +=2)
                                        {
                                                BigInteger bcosig = (sig > 0 )? bco : bco.negate() ;
                                                /* -a = b/z+c*z has real part b*Re(z)/|z|^2+c*Re(z) = Re z *( b/|z|^2+c)
                                                */
                                                BigDecimal negA = BigDecimalMath.add(BigDecimalMath.divideRound(bcosig,z.norm()),cco) ;
                                                negA = negA.multiply(z.re) ;
                                                /* convert to a with round-to-nearest
                                                */
                                                BigInteger a = negA.negate().add(half).toBigInteger() ;
                
                                                /* test the polynomial remainder. if zero, add the term
                                                * to the results.
                                                */
                                                BigIntegerPoly dtst = new BigIntegerPoly(""+bcosig+","+a+","+cco) ;
                                                try 
                                                {
                                                        BigIntegerPoly[] rm = divideAndRemainder(dtst) ;
                                                        if ( rm[1].isZero() )
                                                                res.add(dtst) ;
                                                }
                                                catch ( ArithmeticException ex)
                                                {
                                                }
                                        }
                                }
                        }
                }

                return res;
        } /* i2roots */