Beispiel #1
0
 internal static bool DivisibleBySomeLowPrime(Digits digits, int n)
 {
     if (n == 0 || (digits[0] & 1) == 0)
     {
         Debug.Assert(false, "untested code");
         return(true);
     }
     for (int l = 0; l != LowPrimesProduct.Length; l++)
     {
         Digit product    = LowPrimesProduct[l]
         , productInverse = Digit.TwoAdicInverse(product)
         , r = 0;
         for (int i = 0; i != n; i++)
         {
             Digit mulby;
             unchecked {
                 r += digits[i];
                 if (r < digits[i])
                 {
                     r -= product;
                 }
                 mulby = productInverse * r;
                 Debug.Assert(mulby * product == r, "internal error");
             }
             r = product - Digit2.Hi((UInt64)mulby * product);
         }
         if (Digit.OddGcd(r, product) != 1)
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #2
0
        Mul22S(Digit[] mat, Digits vec1, Digits vec2, int lvec, int[] carrys)
        {
            int   carry1 = 0, carry2 = 0;
            Digit m11 = mat[0], m12 = mat[1], m21 = mat[2], m22 = mat[3];

            if (((m11 | m12 | m21 | m22) & 1U << Digit.BitN - 1) != 0)
            {
                throw new ArgumentException();
            }
            for (int i = 0; i != lvec; i++)
            {
                UInt64 prod11 = (UInt64)m11 * vec1[i]
                , prod12      = (UInt64)m12 * vec2[i]
                , prod21      = (UInt64)m21 * vec1[i]
                , prod22      = (UInt64)m22 * vec2[i]
                , prod1       = unchecked (prod11 + (UInt64)carry1)
                , prod2       = unchecked (prod22 + (UInt64)carry2);
                prod1   = unchecked (prod1 - prod12);
                prod2   = unchecked (prod2 - prod21);
                vec1[i] = Digit2.Lo(prod1);
                vec2[i] = Digit2.Lo(prod2);
                carry1  = unchecked ((int)Digit2.Hi(prod1));
                carry2  = unchecked ((int)Digit2.Hi(prod2));
            }
            carrys[0] = carry1;
            carrys[1] = carry2;
        }
Beispiel #3
0
        static void Mul22U(
            Digit[] mat
            , Digits vec1
            , Digits vec2
            , int lvec
            , Digits carrys
            )
        {
            Digit carry1 = 0, carry2 = 0;
            Digit m11 = mat[0], m12 = mat[1], m21 = mat[2], m22 = mat[3];

            if (m12 > Digit.MaxValue - m11 || m21 > Digit.MaxValue - m22)
            {
                throw new ArgumentException();
            }
            for (int i = 0; i != lvec; i++)
            {
                UInt64 prod11 = (UInt64)m11 * vec1[i] + carry1
                , prod21      = (UInt64)m21 * vec1[i] + carry2
                , prod12      = (UInt64)m12 * vec2[i] + Digit2.Lo(prod11)
                , prod22      = (UInt64)m22 * vec2[i] + Digit2.Lo(prod21);
                vec1[i] = Digit2.Lo(prod12);
                vec2[i] = Digit2.Lo(prod22);
                carry1  = Digit2.Hi(prod11) + Digit2.Hi(prod12);
                carry2  = Digit2.Hi(prod21) + Digit2.Hi(prod22);
            }
            carrys[0] = carry1;
            carrys[1] = carry2;
        }
Beispiel #4
0
        static void Div(
            Digits numer
            , Digit den
            , Reciprocal recip
            , Digits q
            , int n
            , Digits r
            )
        {
            Digit carry = 0;
            int   nLeft = n;

            if (nLeft > 0 && numer[nLeft - 1] < den)
            {
                nLeft--;
                carry = numer[nLeft];
                if (q != null)
                {
                    q[nLeft] = 0;
                }
            }
            if (recip == null && nLeft < 2)
            {
                for (int i = nLeft; i-- != 0;)
                {
                    Digit qest = 0;
                    Digit2.Div((UInt64)carry << Digit.BitN | numer[i]
                               , den
                               , out qest
                               , out carry);
                    if (q != null)
                    {
                        q[i] = qest;
                    }
                }
            }
            else
            {
                if (recip == null)
                {
                    recip = new Reciprocal();
                    DivPrecondition(new Digits(new Digit[] { den }), 1, recip);
                }
                for (int i = nLeft; i-- != 0;)
                {
                    Digit qest = 0;
                    Digit2.Div((UInt64)carry << Digit.BitN | numer[i]
                               , den
                               , recip
                               , out qest
                               , out carry);
                    if (q != null)
                    {
                        q[i] = qest;
                    }
                }
            }
            r[0] = carry;
        }
Beispiel #5
0
        internal static Digit Mul(Digits a, Digit mult, Digits b, int n)
        {
            Digit carry = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp = (UInt64)mult * a[i] + carry;
                b[i]  = Digit2.Lo(dtemp);
                carry = Digit2.Hi(dtemp);
            }
            return(carry);
        }
Beispiel #6
0
        Accumulate(Digits a, Digit mult, Digits b, int n)
        {
            Digit carry = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp = (UInt64)mult * a[i] + b[i] + carry;
                b[i]  = Digit2.Lo(dtemp);
                carry = Digit2.Hi(dtemp);
            }
            return(carry);
        }
Beispiel #7
0
        void _MulFromRight(Digits a, Digits b, Digits c)
        {
            Digit minv = _rightRecip
            , minva0 = unchecked (minv * a[0])
            , mul1 = b[0]
            , mul2 = unchecked (minva0 * mul1)
            , carry1 = Digit2.Hi((UInt64)mul1 * a[0])
            , carry2 = Digit2.Hi((UInt64)mul2 * _mod[0]);
            UInt64 prod1, prod2;

            Debug.Assert(unchecked (mul1 * a[0]) == unchecked (mul2 * _mod[0])
                         , "internal error");
            Digits temp1 = new Digits(_digitN), temp2 = new Digits(_digitN);

            for (int i = 1; i != _digitN; i++)
            {
                prod1        = (UInt64)mul1 * a[i] + carry1;
                prod2        = (UInt64)mul2 * _mod[i] + carry2;
                temp1[i - 1] = Digit2.Lo(prod1);
                temp2[i - 1] = Digit2.Lo(prod2);
                carry1       = Digit2.Hi(prod1);
                carry2       = Digit2.Hi(prod2);
            }
            temp1[_digitN - 1] = carry1;
            temp2[_digitN - 1] = carry2;
            for (int j = 1; j != _digitN; j++)
            {
                mul1  = b[j];
                mul2  = unchecked (minva0 * mul1 + minv * (temp1[0] - temp2[0]));
                prod1 = (UInt64)mul1 * a[0] + temp1[0];
                prod2 = (UInt64)mul2 * _mod[0] + temp2[0];
                Debug.Assert(Digit2.Lo(prod1) == Digit2.Lo(prod2)
                             , "internal error");
                carry1 = Digit2.Hi(prod1);
                carry2 = Digit2.Hi(prod2);
                for (int i = 1; i != _digitN; i++)
                {
                    prod1        = (UInt64)mul1 * a[i] + temp1[i] + carry1;
                    prod2        = (UInt64)mul2 * _mod[i] + temp2[i] + carry2;
                    temp1[i - 1] = Digit2.Lo(prod1);
                    temp2[i - 1] = Digit2.Lo(prod2);
                    carry1       = Digit2.Hi(prod1);
                    carry2       = Digit2.Hi(prod2);
                }
                temp1[_digitN - 1] = carry1;
                temp2[_digitN - 1] = carry2;
            }
            Modular.Sub(temp1, temp2, c, _mod, _digitN);
        }
Beispiel #8
0
        DivPrecondition(Digits denom, int denomN, Reciprocal recip)
        {
            if (denom == null)
            {
                throw new ArgumentNullException();
            }
            if (denomN == 0 || denom[denomN - 1] == 0)
            {
                throw new ArgumentException();
            }
            int   recipBitShift = Digit.BitN - Digit.SigBitN(denom[denomN - 1]);
            Digit dlead2        = denom[denomN - 1]
            , dlead1            = denomN >= 2 ? denom[denomN - 2] : 0
            , dlead0            = denomN >= 3 ? denom[denomN - 3] : 0
            , dShiftHi          = dlead2 << recipBitShift
                         | dlead1 >> 1 >> Digit.BitN - 1 - recipBitShift
                , dShiftLo = dlead1 << recipBitShift
                         | dlead0 >> 1 >> Digit.BitN - 1 - recipBitShift;
            Digit recipMpy, r;

            Digit2.Div((UInt64)(Digit.MaxValue - dShiftHi) << Digit.BitN
                       | Digit.MaxValue - dShiftLo
                       , dShiftHi
                       , out recipMpy
                       , out r);
            if (Digit2.Hi((UInt64)recipMpy * dShiftLo) > r)
            {
                recipMpy -= 1;
            }
            r = (Digit.MaxValue >> recipBitShift) - denom[denomN - 1];
            for (int id = denomN; id-- != 0 && r < recipMpy;)
            {
                UInt64 test1 = (UInt64)r << Digit.BitN
                               | Digit.MaxValue - (id > 0 ? denom[id - 1] : 0)
                    , test2 = (UInt64)recipMpy * denom[id];
                if (test2 > test1)
                {
                    recipMpy -= 1; break;
                }
                test1 = test1 - test2;
                r     = Digit2.Lo(test1);
                if (Digit2.Hi(test1) != 0)
                {
                    break;
                }
            }
            recip._shiftBitN  = recipBitShift;
            recip._multiplier = recipMpy;
        }
Beispiel #9
0
        Decumulate(Digits a, Digit mult, Digits b, int n)
        {
            Digit borrow = 0;

            for (int i = 0; i != n; i++)
            {
                UInt64 dtemp;
                unchecked {
                    dtemp = (UInt64)b[i] - borrow - (UInt64)mult * a[i];
                }
                b[i] = Digit2.Lo(dtemp);
                unchecked { borrow = 0 - Digit2.Hi(dtemp); }
            }
            return(borrow);
        }
Beispiel #10
0
        internal Digit EstQuotient(Digit n2, Digit n1, Digit n0)
        {
            Digit nShiftHi
                = n2 << _shiftBitN | n1 >> 1 >> Digit.BitN - 1 - _shiftBitN
                , nShiftLo
                = n1 << _shiftBitN | n0 >> 1 >> Digit.BitN - 1 - _shiftBitN;
            UInt64 qprod = ((UInt64)nShiftHi << Digit.BitN | nShiftLo)
                           + (UInt64)nShiftHi * _multiplier;

            if ((nShiftLo & 1U << Digit.BitN - 1) != 0)
            {
                qprod += _multiplier >> 1;
            }
            return(Digit2.Hi(qprod));
        }
Beispiel #11
0
        LehmerMat22(UInt64 lead0orig, UInt64 lead1orig, Digit[] mat22)
        {
            Digit lead0h = Digit2.Hi(lead0orig)
            , lead0l = Digit2.Lo(lead0orig)
            , lead1h = Digit2.Hi(lead1orig)
            , lead1l = Digit2.Lo(lead1orig);
            bool  progress = true;
            Digit m00 = 1, m01 = 0, m10 = 0, m11 = 1;

            Debug.Assert(lead0h != 0 &&
                         lead1h != 0 &&
                         ((lead0h | lead1h) & 1U << Digit.BitN - 1) != 0
                         , "internal error");
            while (progress)
            {
                progress = false;
                if (lead0h - 1 > lead1h && lead0h != 0)
                {
                    if (lead0h >> 2 >= lead1h + 2)
                    {
                        Digit  q          = lead0h / (lead1h + 2);
                        UInt64 prod10By11 = (UInt64)q * (m10 + m11)
                        , prod1l          = (UInt64)q * lead1l;
                        Debug.Assert(q > 3, "internal error");
                        if (
                            Digit2.Hi(prod10By11) == 0 &&
                            Digit2.Lo(prod10By11)
                            <= Digit.MaxValue / 2 - m00 - m01
                            )
                        {
                            Digit prod10 = q * m10;
                            progress = true;
                            lead0h
                                -= (Digit)((long)(UInt32)q * lead1h
                                           + Digit2.Hi(prod1l)
                                           + (Digit2.Lo(prod1l) > lead0l ? 1L : 0L));
                            unchecked { lead0l -= Digit2.Lo(prod1l); }
                            m00 += prod10;
                            m01 += Digit2.Lo(prod10By11) - prod10;
                            Debug.Assert((m00 | m01) < 1U << Digit.BitN - 1
                                         , "internal error");
                        }
                    }
                    else
                    {
                        Digit overflowTest;
                        do
                        {
                            m00         += m10;
                            m01         += m11;
                            overflowTest = (m00 | m01) & 1U << Digit.BitN - 1;
                            lead0h      -= lead1h + (lead1l > lead0l ? 1U : 0U);
                            unchecked { lead0l -= lead1l; }
                        } while (overflowTest == 0 && lead0h >= lead1h + 2);
                        progress = true;
                        if (overflowTest != 0)
                        {
                            progress = false;
                            m00     -= m10;
                            m01     -= m11;
                        }
                    }
                }
                if (lead1h - 1 > lead0h && lead1h != 0)
                {
                    if (lead1h >> 2 >= lead0h + 2)
                    {
                        Digit  q           = lead1h / (lead0h + 2);
                        UInt64 prod00And01 = (UInt64)q * (m00 + m01)
                        , prod0l           = (UInt64)q * lead0l;
                        Debug.Assert(q > 3, "internal error");
                        if (
                            Digit2.Hi(prod00And01) == 0 &&
                            Digit2.Lo(prod00And01)
                            <= Digit.MaxValue / 2 - m10 - m11
                            )
                        {
                            Digit prod00 = q * m00;
                            progress = true;
                            lead1h  -= q * lead0h
                                       + Digit2.Hi(prod0l)
                                       + (Digit2.Lo(prod0l) > lead1l ? 1U : 0U);
                            unchecked { lead1l -= Digit2.Lo(prod0l); }
                            m10 += prod00;
                            m11 += Digit2.Lo(prod00And01) - prod00;
                            Debug.Assert((m10 | m11) < 1U << Digit.BitN - 1
                                         , "internal error");
                        }
                    }
                    else
                    {
                        Digit overflowTest;
                        do
                        {
                            m10         += m00;
                            m11         += m01;
                            overflowTest = (m10 | m11) & 1U << Digit.BitN - 1;
                            lead1h      -= lead0h + (lead0l > lead1l ? 1U : 0U);
                            unchecked { lead1l -= lead0l; }
                        } while (overflowTest == 0 && lead1h >= lead0h + 2);
                        progress = true;
                        if (overflowTest != 0)
                        {
                            progress = false;
                            m10     -= m00;
                            m11     -= m01;
                        }
                    }
                }
            }
            Debug.Assert(((m00 | m01 | m10 | m11) & 1U << Digit.BitN - 1) == 0
                         , "internal error");
            mat22[0] = m00;
            mat22[1] = m01;
            mat22[2] = m10;
            mat22[3] = m11;
        }