Exemple #1
0
        /*-----------------------------------------------------------------------*/
        uint squfof_one_cycle(squfof_data_t data, uint mult_idx,
                              uint num_iter, out uint factor)
        {
            /* Perform one unit of work for SQUFOF with one multiplier */

            uint sqrtn         = data.sqrtn[mult_idx];
            uint cutoff        = data.cutoff[mult_idx];
            uint num_saved     = data.num_saved[mult_idx];
            uint multiplier    = 2 * multipliers[mult_idx];
            uint coarse_cutoff = cutoff * multiplier;

            ushort[] saved = data.saved[mult_idx];
            uint     q0    = data.q0[mult_idx];
            uint     p1    = data.p1[mult_idx];
            uint     q1    = data.q1[mult_idx];

            uint  i, j;
            uint  p0    = 0;
            uint  sqrtq = 0;
            ulong scaledn;

            factor = 0;
            for (i = 0; i < num_iter; i++)
            {
                uint q, bits, tmp;

                /* compute (sqrtn+p1)/q1; since this is unity
                 * more than half the time, special case the
                 * division to save some effort */

                tmp = sqrtn + p1 - q1;
                q   = 1;
                if (tmp >= q1)
                {
                    q += tmp / q1;
                }

                /* compute the next numerator and denominator */

                p0 = q * q1 - p1;
                q0 = q0 + (p1 - p0) * q;

                /* In order to avoid trivial factorizations,
                 * save q1 values that are small in a list. Only
                 * values that do not contain factors of the
                 * multiplier must be saved; however, the GCD
                 * is 5x more expensive than all the rest of the
                 * work performed in the loop. To avoid most GCDs,
                 * only attempt one if q1 is less than the cutoff
                 * times the full multiplier
                 *
                 * If the queue overflows (very rare), signal that
                 * this multiplier failed and move on to another one */

                if (q1 < coarse_cutoff)
                {
                    tmp = q1 / IntegerMath.GreatestCommonDivisor(q1, multiplier);

                    if (tmp < cutoff)
                    {
                        if (num_saved >= QSIZE)
                        {
                            data.failed[mult_idx] = true;
                            return(i);
                        }
                        saved[num_saved++] = (ushort)tmp;
                    }
                }

                /* if q0 is a perfect square, then the factorization
                 * has probably succeeded. Most of the squareness
                 * tests out there require multiple divisions and
                 * complicated loops. We can approximate these tests
                 * by doing two things: testing that the number of
                 * trailing zeros in q0 is even, and then testing
                 * if q0 shifted right this many places is 1 mod 8. */

                bits = 0;
                tmp  = q0;
                while ((tmp & 1) == 0)
                {
                    bits++;
                    tmp >>= 1;
                }
                if ((bits & 1) == 0 && ((tmp & 7) == 1))
                {
                    /* q0 is probably a perfect square. Take the
                     * square root by cheating */

                    sqrtq = (uint)(Math.Sqrt((double)q0));

                    if (sqrtq * sqrtq == q0)
                    {
                        /* it *is* a perfect square. If it has
                         * not appeared previously in the list
                         * for this multiplier, then we're almost
                         * finished */

                        for (j = 0; j < num_saved; j++)
                        {
                            if (saved[j] == sqrtq)
                            {
                                break;
                            }
                        }

                        if (j == num_saved)
                        {
                            break;
                        }
                    }
                }

                /* perform the odd half of the SQUFOF cycle */

                tmp = sqrtn + p0 - q0;
                q   = 1;
                if (tmp >= q0)
                {
                    q += tmp / q0;
                }

                p1 = q * q0 - p0;
                q1 = q1 + (p0 - p1) * q;

                if (q0 < coarse_cutoff)
                {
                    tmp = q0 / IntegerMath.GreatestCommonDivisor(q0, multiplier);

                    if (tmp < cutoff)
                    {
                        if (num_saved >= QSIZE)
                        {
                            data.failed[mult_idx] = true;
                            return(i);
                        }
                        saved[num_saved++] = (ushort)tmp;
                    }
                }
            }

            if (sqrtq == 1)
            {
                /* the above found a trivial factor, so this
                 * multiplier has failed */

                data.failed[mult_idx] = true;
                return(i);
            }
            else if (i == num_iter)
            {
                /* no square root found; save the parameters
                 * and go on to the next multiplier */

                data.q0[mult_idx]        = q0;
                data.p1[mult_idx]        = p1;
                data.q1[mult_idx]        = q1;
                data.num_saved[mult_idx] = num_saved;
                return(i);
            }

            /* square root found; the algorithm cannot fail now.
             * Compute the inverse quadratic form and iterate */

            q0      = sqrtq;
            p1      = p0 + sqrtq * ((sqrtn - p0) / sqrtq);
            scaledn = data.n * (ulong)multipliers[mult_idx];
            q1      = (uint)((scaledn - (ulong)p1 * (ulong)p1) / (ulong)q0);

            while (true)
            {
                uint q, tmp;

                tmp = sqrtn + p1 - q1;
                q   = 1;
                if (tmp >= q1)
                {
                    q += tmp / q1;
                }

                p0 = q * q1 - p1;
                q0 = q0 + (p1 - p0) * q;

                if (p0 == p1)
                {
                    q0 = q1;
                    break;
                }

                tmp = sqrtn + p0 - q0;
                q   = 1;
                if (tmp >= q0)
                {
                    q += tmp / q0;
                }

                p1 = q * q0 - p0;
                q1 = q1 + (p0 - p1) * q;

                if (p0 == p1)
                {
                    break;
                }
            }

            /* q0 is the factor of n. Remove factors that exist
             * in the multiplier and save whatever's left */

            q0     = q0 / IntegerMath.GreatestCommonDivisor(q0, multiplier);
            factor = q0;
            return(i);
        }
Exemple #2
0
 public ShanksSquareForms()
 {
     data = new squfof_data_t(MAX_MULTIPLIERS, QSIZE);
 }